Django:在不创建模型的情况下允许下载S3上的各种媒体文件(并隐藏S3存储)
我在S3上有成千上万的媒体文件。
- 这些文件的类型可能是纯文本、HTML、XML、PDF、二进制文件、压缩包等。
- 另外,有些文件可能是经过gzip压缩的。
我想在Django应用中展示这些文件。我不想让用户直接访问S3。在某些情况下,我还想在展示之前对文件进行一些修改。
比如:
- /base/path/file_name_aaa.txt.gz <--- 从S3下载,解压后通过Django展示格式化的文本
- /base/path/file_name_aaa.pdf <--- 从S3下载并通过Django展示为PDF
- /base/path/file_name_bbb.pdf.gz <--- 从S3下载,解压后通过Django展示为PDF
- /base/path/file_name_ccc.xml.gz <--- 从S3下载,解压,替换一些内容,然后通过Django展示为解压后的XML
我已经完成了纯文本的部分:
from boto.s3.connection import S3Connection
import zlib
def get_gzipped_content(stream):
content = ''
for part in stream_decompress(stream):
content += part
return content
def stream_decompress(stream):
'''
decompress s3 gzipped stream
http://stackoverflow.com/questions/12571913/python-unzipping-stream-of-bytes
'''
dec = zlib.decompressobj(16+zlib.MAX_WBITS) # same as gzip module
for chunk in stream:
rv = dec.decompress(chunk)
if rv:
yield rv
conn = S3Connection(aws_key, aws_secret)
fname = 'aaa/bbb/ccc_1234.txt.gz'
key = conn.get_bucket('my_bucket').get_key(fname)
if fname.lower().endswith('.gz'):
content = get_gzipped_content(key)
else:
content = key.get_contents_as_string()
(render content as string in django)
我希望能得到关于其他文件类型和gzip的帮助。
2 个回答
2
除了kubus提到的内容,我还在想怎么让浏览器“显示”文件,而不是“下载”它。
response = HttpResponse(ContentFile(content), content_type=mimetypes.guess_type(attach_id)[0])
if <this file should be forced download, and not render in browser>:
response['Content-Disposition'] = "attachment; filename=%s" % filename
# else, it will try to render in browser.
1
你可以使用一个标准的mimetype模块来根据文件名判断内容类型和编码,比如:
In [1]: import mimetypes
In [2]: mimetypes.guess_type('hello.txt.gz')
Out[2]: ('text/plain', 'gzip')
In [3]: mimetypes.guess_type('hello.pdf.gz')
Out[3]: ('application/pdf', 'gzip')
In [4]: mimetypes.guess_type('hello.pdf')
Out[4]: ('application/pdf', None)