我有一个代码:
def post(self, request, *args, **kwargs):
file = request.FILES["import_file"]
# create a tast with celery and save ID of the task
task_id = importing.delay(file).id
return Response({"task_id": task_id}, content_type="application/json")
当类型(文件)是TemporaryUploadedFile时,我有错误,因为该文件无法写入redis。
我可以取这个临时文件的名字,并将这个名字保存到Redis中。然后芹菜工人可以从redis中获得这个名称并读取文件。但我不确定:在芹菜工人从redis获得其名称之前,该文件能否被删除?
request_finished
信号一发出,TemporaryUploadedFile
就会关闭并移除。当你的Celery工作人员找到该文件时,该文件很可能不再存在。
您应该将文件复制到一个持久的位置,并在完成后让Celery清理文件。
def close(self):
try:
return self.file.close()
except OSError as e:
if e.errno != errno.ENOENT:
# Means the file was moved or deleted before the tempfile
# could unlink it. Still sets self.file.close_called and
# calls self.file.file.close() before the exception
raise
根据TemporaryUploadedFile的close
方法的源代码,如果临时文件被移动,它不会被关闭,所以你可以移动它,并将它的新路径传递给芹菜任务,然后在芹菜任务完成时自己删除它。通过这种方式,您将节省将文件复制到持久位置的时间和资源。
import os
from django.core.files import uploadedfile
file = request.FILES["import_file"]
new_path = '/tmp/import_file'
if isinstance(file, uploadedfile.TemporaryUploadedFile):
os.rename(file.file.name, new_path)
else: # Deal with InMemoryUploadedFile
with open(new_path, 'wb') as f:
for chunk in file.chunks():
f.write(chunk)
task_id = importing.delay(new_path).id