使用烧瓶中的 send_file() 时文件损坏,pymongo gridfs 中的数据
Posted
技术标签:
【中文标题】使用烧瓶中的 send_file() 时文件损坏,pymongo gridfs 中的数据【英文标题】:File corrupted when using send_file() from flask, data from pymongo gridfs 【发布时间】:2021-11-07 00:56:03 【问题描述】:好吧,我的英文不好,而且标题可能看起来很奇怪。
反正我现在正在用flask搭建一个可以存储文件的网站,mongodb就是数据库。
文件上传、文档插入功能都没有问题,奇怪的是flasksend_file()
发送的文件被无故截断。这是我的代码
from flask import ..., send_file, ...
import pymongo
import gridfs
#...
@app.route("/record/download/<record_id>")
def api_softwares_record_download(record_id):
try:
#...
file = files_gridfs.find_one("_id": record_id)
file_ext = filetype.guess_extension(file.read(2048))
filename = "-".format(
app["name"],
record["version"],
".".format(file_ext) if file_ext else "",
)
response = send_file(file, as_attachment=True, attachment_filename=filename)
return response
except ...
例如,原始图像文件为 553KB。但是响应正文返回 549.61KB,并且图像已损坏。但是如果我只是直接将文件写入我的磁盘
#...
with open('test.png', 'wb+') as file:
file.write(files_gridfs.find_one("_id": record_id).read())
图片文件大小为553KB,图片可读。
当我用VS Code的文本编辑器比较这两个文件时,我发现正确的文件以�PNG
开头,但损坏的文件以�ϟ8���>�L�y
开头
search the corrupted file head in the correct file
我尝试使用Blob
对象并从浏览器下载它。没有区别。
我的代码有什么问题还是我误用了send_file()
?还是应该使用flask_pymongo
?
【问题讨论】:
【参考方案1】:有趣的是,我发现我的代码有什么问题。
我就是这样解决的
...file.read(2048)
file.seek(0)
...
file.read(2048)
file.seek(0)
...
response = send_file(file, ...)
return response
原因如下:
由于某些原因,我使用filetype
来检测文件的扩展名和mime类型,所以我将2048B发送到filetype
进行检测。
file_ext = filetype.guess_extension(file.read(2048))
file_mime = filetype.guess_mime(file.read(2048)) #this line wasn't copied in my question. My fault.
我刚刚从pymongo API 了解到python(或pymongo
或gridfs
,以前对此完全不了解)使用游标读取文件。当我尝试使用file.seek()
查找光标的位置时,它返回4096
。所以当我在send_file()
中再次调用file.read()
时,光标从4096B 读取到文件头。 549+4=553,这就是问题所在。
最后我在每次 read()
操作后将光标设置为位置 0,它会返回正确的文件。
如果你和我一样犯了同样的错误,希望这能有所帮助。
【讨论】:
以上是关于使用烧瓶中的 send_file() 时文件损坏,pymongo gridfs 中的数据的主要内容,如果未能解决你的问题,请参考以下文章
在 Pythonanywhere 上的烧瓶中替代 send_file()?
尽管有 200 条消息,flask send_file 仍然失败 [重复]
使用 mysql 和烧瓶登录的 Flask-sqlalchemy 损坏管道错误 32
使用Python Flask中的send_file发送视频时移动设备发生错误http://mattspitz.me/2013/11/20/serving-authenticated-media-wit