django - 在 Django Celery Queue 中从 Redis 存储和下载文件
问题描述
我在我的应用程序中压缩了大量文件,这会导致性能问题。所以现在我决定将文件压缩到一个单独的队列中,将结果存储在 Redis 中,并在该过程完成后立即提供给用户。我将数据存储在 Redis 中以使其更快,并且因为我不需要将文件存储在服务器硬盘上。
这是我的task.py:
@shared_task
def zip_files(filenames, key):
compression = zipfile.ZIP_STORED
s = BytesIO()
zf = zipfile.ZipFile(s, mode="w")
for fpath in filenames:
fdir, fname = os.path.split(fpath)
zf.write(fpath, fname, compress_type=compression)
zf.close()
caches['redis'].set(hash_key, {'file':s.getvalue()})
return hash_key
然后这是我的简单下载视图:
def folder_cache(request, folder_hash):
cache_data = caches['redis'].get(folder_hash)
if cache_data:
response = FileResponse(cache_data['file'], content_type="application/x-zip-compressed")
response['Content-Disposition'] = 'attachment; filename=hello.zip'
response['Content-Length'] = len(cache_data['file'])
return response
return HttpResponse("Cache expired.")
问题是我只能下载文件的一部分,然后下载被“网络连接丢失”消息停止。下载的文件似乎包含一组数字(不是二进制数据)。但我不知道,也许我使用 FileResponse 错误?或者我需要在将数据放入 Redis 缓存之前/之后序列化数据?
我还在 shell 中尝试了相同的代码,当我使用 fopen 并将数据从 Redis 缓存直接写入服务器硬盘时,它可以工作。
解决方案
最后,我发现我只需要将文件数据包装到 ContentFile 类中。所以这是最新的工作代码:
def folder_cache(request, folder_hash):
cache_data = caches['redis'].get(folder_hash)
if cache_data:
if (cache_data['status'] == 'complete'):
...
response = FileResponse(ContentFile(cache_data['file']), content_type="application/x-zip-compressed")
response['Content-Disposition'] = 'attachment; filename={}'.format(filename)
response['Content-Length'] = len(cache_data['file'])
return response
推荐阅读
- xcode - Xcode:由于权限问题,无法启动 macOS 命令行程序
- python - 石头剪刀布游戏重置功能
- python - 函数调用堆栈:train_function 错误
- matrix - 可以用 scale + rotate3d 替换 skew
- aem - AEM 使用 HTL 的不同方式
- linux - os.Stdout 和 os.File 有什么区别
- rust - FnOnce 的泛型,返回具有生命周期的未来
- oracle19c - Oracle 数据泵导入 TSTZ 版本
- kubernetes - kubectl - 如何使用基本身份验证从 url 创建资源
- yii2 - yii2 - 多行从一个表单加载到同一个表中