上一篇向 大家展示了如何利用openpyxl库和临时文件将表格文件数据流化,数据流的主要目的是放于网络 展示,本篇向大家展示如何在网站使用这个数据流。
此次操作使用的网络框架是django,如果对其基本配置还不了解,也没关系,和其他的框架并不是很大区别,可以参考我去年写的一些文章。
数据流转换文件
源数据
因为简单demo,所以没有设置数据库,在这里直接读取本地文件转换为二进制,下面的file_content就代表了这个文件。
with open('static/data.xlsx', 'rb') as f:
file_content = f.read()
响应头
headers = {
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment;filename=data.xlsx'
}
配置响应头以后,可以在下载的时候对文件带上文件名。
基础响应方式HttpResponse
利用django中的HttpResponse响应二进制数据,访问对应的路由,可以直接获得文件下载。
resp = HttpResponse(content=file_content, headers=headers)
打开文件也是个正常的文件。
文件响应方式FileResponse
借助上一篇提到的NamedTemporaryFile,我们将其传递出去,设置了文件名参数后,不需要额外填写响应头。
tmp = NamedTemporaryFile(delete=False)
tmp.write(file_content)
tmp.seek(0)
resp = FileResponse(tmp, filename='data2.xlsx')
这里不能用前文所述的上下文管理器,对于网站来说,在他响应的过程中,文件会被关闭。对于上面的临时文件而言,这是一个糟糕的特性,意味着我们既不能手动删除,也不能用管理器删除。长期使用这种方式会导致临时文件堆积。建议还是用基础响应返回。
操作excel数据流
结合前两篇文章的操作方法,在这里实现一次Excel文件的修改和响应,完整的django视图函数如下:
def download(request):
with open('static/data.xlsx', 'rb') as f:
file_content = f.read()
headers = {
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment;filename=data.xlsx'
}
with NamedTemporaryFile(delete=False) as tmp:
tmp.write(file_content)
tmp.seek(0)
wb = load_workbook(tmp)
os.remove(tmp.name)
ws = wb.active
print(ws.cell(1, 1).value)
wb.copy_worksheet(ws)
with NamedTemporaryFile(delete=False) as tmp2:
wb.save(tmp2.name)
tmp2.seek(0)
stream = tmp2.read()
os.remove(tmp2.name)
resp = HttpResponse(content=stream, headers=headers)
return resp
代码中借助临时文件,将excel文件数据流先写入文件,再通过openpyxl读取,最后将其保存为新的临时文件后返回响应。
数据压缩
如果要存储这部分数据,没必要完整存储原始部分,我们可以用zlib来压缩这个数据,zlib是个自带的库。
压缩与解压:
new_content = zlib.compress(file_content)
old_content = zlib.decompress(new_content)
对于这个文件,默认的压缩等级下,新数据占比为78%
对于数据库而言,使用二进制字段就会比字符串占的空间小很多,经过压缩会更小一些。