Django 后端处理文件下载返回乱码数据,可以下载但无法打开?

新手上路,请多包涵

VUE

<template>
  <div>
    <button @click="downloadFile" id="btn">下载文件</button>

  </div>
</template>

<script>
import axios from 'axios';

export default {
  methods: {
    downloadFile() {
      const filename = '1.docx'; // 文件名,根据需求进行设置
      axios.post('http://127.0.0.1:8000/api/videodownload/', { filename }, {responseType: 'blob'})
        .then(response => {
          const url = window.URL.createObjectURL(new Blob([response.data]));
          const link = document.createElement('a');
          link.href = url;
          link.setAttribute('download', filename);
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
          console.dir(response)
        })
        .catch(error => {
          console.error('文件下载失败', error);
        });
    
  }
};
</script>

DJANGO


@csrf_exempt
def videodownload(request):
    body_unicode = request.body.decode('utf-8')
    data = json.loads(body_unicode)
    filename = data.get('filename')
    download_file_path = os.path.join(settings.BASE_DIR, "studownload", filename)

    if os.path.exists(download_file_path):
        response = FileResponse(open(download_file_path, 'rb'),filename=filename,)
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition']= 'attachment'
        return response
    else:
        return JsonResponse({'status': 'HttpResponse', 'msg': 'Excel下载失败'})

可以下载文件,但是打不开

只有txt格式的文件可以正常打开
image.png
返回的response中的data均为乱码
image.png
image.png
求帮助解决

阅读 926
avatarAI BotBETA

你的问题是关于Django后端处理文件下载时返回乱码数据,并且文件可以下载但无法打开。首先,这个问题可能是因为你的Django后端在返回文件时,Content-Type没有设置正确。对于非文本文件(如docx、xlsx等),应该使用application/octet-stream作为Content-Type。你的代码中已经设置了这一点,所以问题可能出在其他地方。

另一个可能的问题是,你在前端使用Blob对象处理返回的数据时,可能没有正确处理二进制数据。Blob构造函数接受一个包含ArrayBuffer, ArrayBufferView, Blob, DOMString等对象的Array,或者以上对象之一,但你的代码中直接将response.data作为Blob的内容,这可能导致数据格式错误。

对于这个问题,我建议你在Django后端不要直接返回文件的二进制内容,而是将文件保存到一个临时文件中,然后将这个临时文件的路径返回给前端。前端在接收到这个路径后,可以直接使用这个路径来下载文件,这样可以避免处理二进制数据的问题。

以下是修改后的代码:

Django 后端:

import tempfile
from django.http import JsonResponse
from django.http.response import FileResponse

@csrf_exempt
def videodownload(request):
    body_unicode = request.body.decode('utf-8')
    data = json.loads(body_unicode)
    filename = data.get('filename')
    download_file_path = os.path.join(settings.BASE_DIR, "studownload", filename)

    if os.path.exists(download_file_path):
        # 创建一个临时文件,将需要下载的文件内容复制到临时文件中
        with open(download_file_path, 'rb') as f:
            with tempfile.NamedTemporaryFile(delete=False) as tmp:
                tmp.write(f.read())
                tmp_file_path = tmp.name

        # 返回临时文件的路径
        return JsonResponse({'file_path': tmp_file_path})
    else:
        return JsonResponse({'status': 'HttpResponse', 'msg': 'Excel下载失败'})

Vue 前端:

<template>
  <div>
    <button @click="downloadFile" id="btn">下载文件</button>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  methods: {
    downloadFile() {
      const filename = '1.docx'; // 文件名,根据需求进行设置
      axios.post('http://127.0.0.1:8000/api/videodownload/', { filename })
        .then(response => {
          const file_path = response.data.file_path;
          const link = document.createElement('a');
          link.href = file_path;
          link.setAttribute('download', filename);
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
          console.dir(response)
        })
        .catch(error => {
          console.error('文件下载失败', error);
        });
    }
  }
};
</script>

这样修改后,前端直接使用文件的路径来下载文件,不需要处理二进制数据,应该可以解决你的问题。

另外,需要注意的是,由于我将临时文件设置为delete=False,所以在程序结束时,你需要手动删除这些临时文件,否则可能会造成磁盘空间被占用。你可以在你的Django应用中添加一个清理临时文件的逻辑,比如定时任务或者应用启动时清理。

1 个回答
# 换成这两个响应头试试
response['Content-Type'] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

response['Content-Disposition'] = "Content-Disposition", "attachment; filename*=utf-8''模板.xlsx"
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题