对于通过设置form表单POST方法进入的文件对象,flask创建了一个FileStorage对象进行存储
该对象可以直接被用来put到mongodb中的GridFs
# class attachment(db.Document)
attachment.file.put(f, filename=f.filename)
也可以存储到本地
# 文件存储路径 target
target = "/".join([target, filename])
f.save(target)
但是每次被put之后,再进行存储本地时就会导致存储到本地的文件length为0
查找了一下存储原理,FileStorage存储后会read到end,所以第二次进行存储的时候,文件已经无法继续read
解决方法是:
在第一次put之后
f.stream.seek(0)
其实后面了解GridFS之后,其实不太需要再保存到本地
如何使用GridFs存储文件,可以自行baidu
举个demo
@edit.route('/upattachment/<string:a_id>', methods=['POST'])
def upattachment(a_id):
# get article
article = Article.objects.get_or_404(id=ObjectId(a_id))
f = request.files['file']
attachment = Attachment(origin_filename=f.filename, extension=os.path.splitext(f.filename)[1])
attachment.file.put(f, filename=f.filename)
article.attachments.append(attachment)
article.save()
return jsonify({"filename": f.filename, "stat": "success"})
@edit.route('/downattachment')
def download_attachment():
# get args
filename = request.args.get('filename')
a_id = request.args.get('aid')
article = Article.objects.get_or_404(id=ObjectId(a_id))
attachment = article.find_attachments(filename)[0]
def gen_mongo(file):
# file is mongodb.FileField.file
while 1:
chunk = file.read(256 * 1024)
if not chunk:
break
yield chunk
response = Response(gen_mongo(attachment.file), content_type='application/octet-stream')
response.headers['Content-disposition'] = 'attachment;filename=%s' % filename
response.content_length = attachment.file.length
return response