我有一个远程存储项目,当用户请求他的文件时,django服务器在本地检索并存储文件(用于某些处理)作为临时文件,然后使用mod x-sendfile将其提供给用户。我希望tempfile在提供给用户后肯定会被删除。
在文档中声明NamedTemporaryFile删除参数,如果设置False
导致删除文件,之后所有引用都消失了。但是当用户为tempfile提供服务时,它不会被删除。如果我在下载的情况下设置了delete = True,我会得到"在此服务器上找不到请求的URL /ServeSegment/Test.jpg/。"
以下是列出用户文件的视图:
def file_profile(request):
obj = MainFile.objects.filter(owner=request.user)
context = {'title': 'welcome',
'obj': obj
}
return render(request, 'ServeSegments.html', context=context)
这是一个视图,它可以检索,临时存储并提供所请求的文件:
def ServeSegment(request, segmentID):
if request.method == 'GET':
url = 'http://192.168.43.7:8000/foo/'+str(segmentID)
r = requests.get(url, stream=True)
if r.status_code == 200:
with tempfile.NamedTemporaryFile(dir=
'/tmp/Files', mode='w+b') as f:
for chunk in r.iter_content(1024):
f.write(chunk)
response = HttpResponse()
response['Content-Disposition'] = 'attachment; segmentID={0}'.format(f.name)
response['X-Sendfile'] = "{0}".format(f.name)
return response
else:
return HttpResponse(str(segmentID))
我想如果我可以设法在语句中返回响应,然后写完最后一个块,它会按照我的意愿工作,但我找不到关于如何确定我们是否在最后一个循环中的解决方案(没有是hackish)。
我该怎么做才能提供tempfile并在之后删除?
答案 0 :(得分:2)
文件处理程序关闭后,tempfile
创建的任何文件都将被删除。在您的情况下,退出with
语句时。 delete=False
参数会阻止此行为,并将删除更新到应用程序。在<{3}}处理程序发送文件后,可以删除该文件,该文件将在发送响应后取消链接文件。
您的示例对该文件不执行任何操作,因此您可能希望直接使用registering a signal或StreamingHttpResponse
来流式传输内容。但正如你所说&#34;将文件存储在本地(用于某些处理)&#34; ,我建议在没有创建任何临时文件的情况下进行处理,只能使用流。< / p>
答案 1 :(得分:2)
添加避免使用信号的通用答案(基于Cyrbil&#39;)
import os
import tempfile
from django.http import FileResponse
def my_view(request):
try:
tmp = tempfile.NamedTemporaryFile(delete=False)
with open(tmp.name, 'w') as fi:
# write to your tempfile, mode may vary
response = FileResponse(open(tmp.name, 'rb'))
return response
finally:
os.remove(tmp.name)
答案 2 :(得分:0)
一次性文件 该问题的解决方案是不要在NamedTemporaryFile中使用并处理异常。目前,您的文件在读取前已被删除。最后返回
f.seek(0)
return FileResponse(f, as_attachment=True, filename=f.name)
读取完成后,临时文件将关闭,因此将被删除。
非一次性文件
对于偶然发现的人,没有自动处理的文件柄。
从其他答案来看,信号似乎是一个合理的解决方案,但是传递数据需要更改受保护的成员。我不确定将来会如何支持。我还发现,whp的解决方案在当前版本的Django中不起作用。我能想到的最适合未来的版本是猴子修补文件输出,以便在关闭时删除文件。 Django在发送文件结束时关闭了文件句柄,我看不到这一变化。
def my_view(request):
tmp = tempfile.NamedTemporaryFile(delete=False)
try:
# write file tmp (remember to close if re-opening)
# after write close the file (if not closed)
stream_file = open(tmp.name, 'rb')
# monkey patch the file
original_close = stream_file.close
def new_close():
original_close()
os.remove(tmp.name)
stream_file.close = new_close
# return the result
return FileResponse(stream_file, as_attachment=True, filename='out.txt')
except Exception:
os.remove(output.name)
raise