使用Pyramid服务GridFS文件

2 投票
3 回答
694 浏览
提问于 2025-04-17 13:53

我想知道用Pyramid从GridFS提供文件的最佳和最简单的方法是什么。我使用nginx作为代理服务器(用于ssl),并用waitress作为我的应用服务器。

我需要提供的文件类型有:mp3、pdf、jpg、png。

这些文件应该可以通过以下网址访问:“/files/{userid}/{filename}”。

现在,文件在客户端能被正确的应用程序打开,因为我在代码中明确设置了内容类型,像这样:

if filename[-3:] == "pdf":
    response = Response(content_type='application/pdf')

elif filename[-3:] in ["jpg", "png"]:
    response = Response(content_type='image/*')

elif filename[-3:] in ["mp3"]:
    response = Response(content_type='audio/mp3')

else:
    response = Response(content_type="application/*")

response.app_iter = file   #file is a GridFS file object
return response

唯一的问题是,我无法正确地流式播放mp3文件。我使用audio.js来播放它们。它们可以打开并播放,但没有显示曲目长度,而且我无法快进。我知道这和“accept-ranges”属性有关,但我似乎无法正确设置。这个问题是和nginx还是waitress有关?还是我只是没有正确设置头信息?

我想用像return FileResponse(file)这样简单的方式,正如这里所说的,但我的文件并不是直接来自文件系统……有没有一种即插即用的方法可以让这个工作?

任何建议都非常感谢!

非常感谢你的帮助!

3 个回答

0

另一种方法(在 Python 2.7 上使用 Pyramid 1.5.7):

fs = GridFS(request.db, 'MyFileCollection')
grid_out = fs.get(file_id)

response = request.response
response.app_iter = FileIter(grid_out)
response.content_disposition = 'attachment; filename="%s"' % grid_out.name

return response
1

我刚刚在Pyramid 1.4和Python 3中解决了这个问题,而且没有使用paste这个依赖。

看起来“conditional_response=True”和“content_length”这两个属性很重要:

f = request.db.fs.files.find_one( { 'filename':filename, 'metadata.bucket': bucket } )

fs = gridfs.GridFS( request.db )

with fs.get( f.get( '_id') ) as gridout:
    response = Response(content_type=gridout.content_type,body_file=gridout,conditional_response=True)
    response.content_length = f.get('length')
    return response
1

我在这个博客上找到了一个解决方案。

这个方法是使用一个修改过的DataApp,它来自paste.fileapp。具体的细节都在那篇文章里,现在我的应用程序的表现正是我想要的样子!

撰写回答