使用Pyramid服务GridFS文件
我想知道用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
。具体的细节都在那篇文章里,现在我的应用程序的表现正是我想要的样子!