如何在Flask中将上传的文件存储到MongoDB?

3
在我的Flask项目中,我正在尝试使用MongoDB实现文件上传。从这个上传教程获取灵感后,我成功地上传了一个文件并将其存储在文件系统中。现在,我想使用这些mongoengine文档将其存储到MongoDB中。
我的当前文档定义如下:
class UserDocument(mongoDb.Document):
    created = mongoDb.DateTimeField(default=datetime.utcnow, required=True)
    filename = mongoDb.StringField()
    _file = mongoDb.FileField()

我上传并存储了一个文件,具有以下视图:

@app.route('/upload', methods=['GET', 'POST'])
def mytickets():
    if request.method == 'POST':
        file = request.files['file']
        if file and isAllowedFile(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))  # This works!
            userDoc = UserDocument()
            userDoc.filename = filename
            userDoc._file.put(file, content_type=file.content_type)
            userDoc.save()
        else:
            return 'We don\'t allow this file extension.'

    return render_template('upload.html')

文件已在文件系统中创建,因此存在文件。在命令行上,我验证了MongoDB中有一个文档,但似乎_file的内容为空:
>>> UserDocument.objects.count()
1
>>> d = UserDocument.objects.first()
>>> d._file.read()
''

我想可能是因为无法在命令行上显示图像数据,所以我想知道如何再次通过Flask显示文档。为此,我制作了一个简单的Flask视图来展示一个文件:

@app.route('/show')
def showSomething():
    doc = UserDocument.objects.first()
    return doc._file.read()

尽管如此,这里没有返回任何内容,可能是因为文件从未被写入MongoDB,或者是因为我的showSomething不正确,或者两者都有。

有人知道我在这里做错了什么吗?欢迎提供所有提示!

[编辑] 我尝试读取文件的内容并将其添加到文档中。这使我进一步了解了一点(请参见下文),因为read()现在输出一些十六进制内容。问题是我不明白从文件上传中读取它与从Flask文件上传获取它有什么区别。最后;是否有一种简单的方法使用Flask在浏览器中显示输出?

>>> from app.documents import UserDocument
>>> UserDocument.objects.count()
0
>>> f = open('/Users/kramer65/repos/tc/app/static/uploads/IMG_7599.JPG', 'r')  # I'm on MacOSX, so 'rb' doesn't exist
>>> userdoc = UserDocument()
>>> userdoc.filename = 'blabla.jpg'
>>> userdoc._file.put(f, content_type='image/jpeg')
>>> userdoc.save()
<UserDocument: UserDocument object>
>>> UserDocument.objects.count()
1
>>> d = UserDocument.objects.first()
>>> d._file.read()
'\xff\xd8\xff\xe1%\xfeExif\x00\x00II*\x00\x08\x00\x00\x00\t\x00\x0f etc. etc.'
>>> d._file.read()
''  # Why oh why is it the second time suddenly an empty string?!

1
你尝试过用“rb”模式打开刚保存的文件并将其传递给put方法吗? - Dragu
@Dragu - 感谢你的建议。我尝试了你的建议并将结果添加到我的上面的问题中。这似乎有所作为,但read()方法仍然输出空字符串。还有其他想法吗? - kramer65
@Dragu - 我在我的问题中编辑了我的编辑,因为我现在从.read()获得一些十六进制输出。奇怪的是,第二次调用.read()时它不会输出任何内容(请参见上文)。也许还有其他想法吗? :S - kramer65
不知道为什么read()只工作了一次。我认为你必须检查一下它在mongoengine源代码中的工作方式 :) - Dragu
有点晚加入,但这个简单的原因是因为它是一个 IO 对象,它记住了你读取数据的索引位置。你可以使用 .seek(0) 重置内部计数器。 - McSebi
1个回答

1
第二次调用read()返回空字符串,因为第一次已经读取并返回了整个内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接