Django创建FileResponse时为何返回WinError32权限错误?
问题:FileResponse后删除文件报
PermissionError: [WinError 32] 在temp文件夹生成video.mp4作为附件发送给用户后删除,但执行os.remove(file_path)时返回PermissionError: [WinError 32],是否是删除过早导致?相关代码如下:
def download_video(request): if request.method == 'POST': link_input_data = request.POST.get('link_input_field') # todo change to use django forms later download_cda.start_download(link_input_data) file_path = "temp\\" + "video.mp4" response = None try: file = open(file_path, "rb") response = FileResponse(file, as_attachment=True, filename="video.mp4") except Exception as e: print(e) # todo add exception code finally: os.remove(file_path) return response else: form = UrlForm() return render(request, 'index.html', {"url_form": form})
原因分析
就是删除时机过早:
- FileResponse采用流式传输,不会立即把整个文件读入内存并发送给客户端,而是在后续响应处理过程中逐步读取文件内容。你在finally块里调用
os.remove时,文件还被打开的file句柄占用,同时Django的响应流程还在依赖这个文件,Windows系统会因为文件被进程占用而拒绝删除操作(WinError32对应“文件正在被另一个进程使用,无法访问”)。 - 代码中直接
open文件但没有手动关闭句柄,进一步加剧了文件被占用的情况。
解决方法
方案1:利用响应回调延迟删除(适合大文件)
通过add_post_render_callback让文件在响应完全发送给客户端后再删除,此时文件已不再被占用:
def download_video(request): if request.method == 'POST': link_input_data = request.POST.get('link_input_field') download_cda.start_download(link_input_data) file_path = "temp\\video.mp4" try: # 使用with上下文管理器自动关闭文件句柄 with open(file_path, "rb") as file: response = FileResponse(file, as_attachment=True, filename="video.mp4") # 定义回调函数,响应完成后删除文件 def delete_file(response): os.remove(file_path) response.add_post_render_callback(delete_file) except Exception as e: print(e) return HttpResponse("文件处理出错", status=500) return response else: form = UrlForm() return render(request, 'index.html', {"url_form": form})
方案2:读取文件到内存后删除(适合小文件)
把文件内容全部读入内存,再删除原文件,最后返回内存中的内容:
def download_video(request): if request.method == 'POST': link_input_data = request.POST.get('link_input_field') download_cda.start_download(link_input_data) file_path = "temp\\video.mp4" response = None try: with open(file_path, "rb") as file: file_content = file.read() # 文件已读入内存,此时可以安全删除 os.remove(file_path) response = HttpResponse(file_content, content_type='video/mp4') response['Content-Disposition'] = 'attachment; filename="video.mp4"' except Exception as e: print(e) return HttpResponse("文件处理出错", status=500) return response else: form = UrlForm() return render(request, 'index.html', {"url_form": form})
注意:此方法不适合大文件,会占用过多内存。
内容的提问来源于stack exchange,提问作者Szymon42214
相关产品推荐
相关产品推荐

