Django从URL下载文件问题:现有代码无法返回目标文件如何修复?
修复从远程URL获取文件并返回下载的问题
你的代码问题在于直接将远程URL的字符串传给了HttpResponse,所以返回的是字符串example.com/video.mp4的内容,而不是远程URL对应的文件。要解决这个问题,需要先请求远程URL获取文件内容,再把内容返回给用户。
修复方案
1. 使用requests库(需先安装:pip install requests)
import requests from django.http import HttpResponse, Http404 def download(request): # 注意补充完整的URL协议头(http/https) remote_url = 'https://example.com/video.mp4' file_name = 'video.mp4' try: # 流式请求避免大文件占用过多内存 remote_response = requests.get(remote_url, stream=True) remote_response.raise_for_status() # 捕获HTTP请求错误 # 创建Django响应,设置正确的内容类型和下载头 django_response = HttpResponse( remote_response.content, content_type=remote_response.headers.get('Content-Type', 'application/octet-stream') ) django_response['Content-Disposition'] = f'attachment; filename="{file_name}"' return django_response except requests.exceptions.RequestException as e: # 处理请求异常,返回404错误 raise Http404(f"无法获取远程文件: {str(e)}")
2. 使用Django自带urllib(无需额外依赖)
from urllib.request import urlopen from urllib.error import URLError, HTTPError from django.http import HttpResponse, Http404 def download(request): remote_url = 'https://example.com/video.mp4' file_name = 'video.mp4' try: with urlopen(remote_url) as remote_file: file_content = remote_file.read() # 获取远程文件的Content-Type,默认用二进制流类型 content_type = remote_file.headers.get_content_type() or 'application/octet-stream' django_response = HttpResponse(file_content, content_type=content_type) django_response['Content-Disposition'] = f'attachment; filename="{file_name}"' return django_response except (URLError, HTTPError) as e: raise Http404(f"无法获取远程文件: {str(e)}")
3. 处理大文件:使用流式响应
如果远程文件体积较大,建议用StreamingHttpResponse流式返回,避免内存溢出:
import requests from django.http import StreamingHttpResponse, Http404 def download(request): remote_url = 'https://example.com/video.mp4' file_name = 'video.mp4' try: remote_response = requests.get(remote_url, stream=True) remote_response.raise_for_status() django_response = StreamingHttpResponse( remote_response.iter_content(chunk_size=8192), content_type=remote_response.headers.get('Content-Type', 'application/octet-stream') ) django_response['Content-Disposition'] = f'attachment; filename="{file_name}"' return django_response except requests.exceptions.RequestException as e: raise Http404(f"无法获取远程文件: {str(e)}")
关键注意点
- 必须给远程URL补充完整的协议头(
http://或https://),否则无法正确请求资源。 - 要添加异常处理,避免因网络错误、远程文件不存在等情况导致服务崩溃。
- 大文件场景优先使用流式响应,减少服务器内存占用。
内容的提问来源于stack exchange,提问作者user17657114
相关产品推荐
相关产品推荐

