You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中将字节转换为用户可下载文件?含JS实现方案

Django 数据库字节数据转可下载文件实现方案

方案一:后端直接返回下载响应

这种方式无需前端额外处理,后端构造响应头让浏览器直接触发下载,是最常用的实现方式。

实现步骤

  1. 假设数据模型(根据你的实际模型调整):
from django.db import models

class StoredFile(models.Model):
    filename = models.CharField(max_length=255)
    file_bytes = models.BinaryField()
    content_type = models.CharField(max_length=100)  # 例如 'image/png'、'application/pdf'
    file_size = models.IntegerField()
  1. 编写视图函数:
from django.http import HttpResponse
from django.utils.http import urlquote

def download_file(request, file_id):
    # 从数据库获取文件信息
    stored_file = StoredFile.objects.get(id=file_id)
    
    # 构造响应,传入字节数据和正确的内容类型
    response = HttpResponse(stored_file.file_bytes, content_type=stored_file.content_type)
    
    # 设置下载头:attachment 强制浏览器下载,filename 指定保存的文件名
    # 使用 urlquote 处理含特殊字符的文件名
    response['Content-Disposition'] = f'attachment; filename="{urlquote(stored_file.filename)}"'
    
    # 可选:设置文件大小,帮助浏览器显示下载进度
    response['Content-Length'] = str(stored_file.file_size)
    
    return response
  1. 配置路由:
    在项目的urls.py中添加路由:
from django.urls import path
from .views import download_file

urlpatterns = [
    # 其他路由...
    path('download/<int:file_id>/', download_file, name='download_file'),
]
  1. 前端使用:
    直接通过链接触发下载:
<a href="{% url 'download_file' file_id=1 %}">下载文件</a>

方案二:前端JavaScript处理下载

如果需要前端做前置逻辑(比如下载确认、批量操作),可以让后端返回字节数据,前端通过JS生成下载链接。

实现步骤

  1. 后端接口视图:
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt  # POST请求需要,GET请求可省略
def get_file_bytes(request, file_id):
    stored_file = StoredFile.objects.get(id=file_id)
    
    # 返回字节数据,同时在响应头传递文件名和内容类型
    response = HttpResponse(stored_file.file_bytes, content_type=stored_file.content_type)
    response['X-Filename'] = stored_file.filename
    response['X-Content-Type'] = stored_file.content_type
    
    return response
  1. 前端JavaScript代码:
async function triggerDownload(fileId) {
    try {
        const res = await fetch(`/get-file-bytes/${fileId}/`);
        if (!res.ok) throw new Error('文件请求失败');
        
        // 从响应头读取文件名和内容类型
        const filename = res.headers.get('X-Filename');
        const contentType = res.headers.get('X-Content-Type');
        
        // 将响应转为Blob对象
        const blob = await res.blob();
        
        // 创建临时下载链接并触发点击
        const downloadUrl = URL.createObjectURL(blob);
        const aTag = document.createElement('a');
        aTag.href = downloadUrl;
        aTag.download = filename;
        document.body.appendChild(aTag);
        aTag.click();
        
        // 清理临时资源
        document.body.removeChild(aTag);
        URL.revokeObjectURL(downloadUrl);
    } catch (err) {
        console.error('下载错误:', err);
        alert('文件下载失败,请重试');
    }
}
  1. 前端调用示例:
<button onclick="triggerDownload(1)">点击下载</button>

注意事项

  • 处理大文件时,推荐使用FileResponse替代HttpResponse,它支持流式传输,避免内存占用过高:
from django.http import FileResponse
from io import BytesIO

def download_large_file(request, file_id):
    stored_file = StoredFile.objects.get(id=file_id)
    file_stream = BytesIO(stored_file.file_bytes)
    response = FileResponse(file_stream, content_type=stored_file.content_type)
    response['Content-Disposition'] = f'attachment; filename="{urlquote(stored_file.filename)}"'
    return response
  • 文件名包含中文或特殊字符时,必须用urlquote编码,避免浏览器解析错误。

内容的提问来源于stack exchange,提问作者user19661285

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:09:32