当前位置: 首页 > 知识库问答 >
问题:

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

孙玺
2024-04-28

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_exemptdef 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
求帮助解决

共有1个答案

金坚
2024-04-28

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

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

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

以下是修改后的代码:

Django 后端:

import tempfilefrom django.http import JsonResponsefrom django.http.response import FileResponse@csrf_exemptdef 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应用中添加一个清理临时文件的逻辑,比如定时任务或者应用启动时清理。

 类似资料:
  • 下载文件功能,电脑下载可以正常打开,手机下载无法打开,或者打开乱码 后台代码 前端下载

  • 问题内容: 我是使用Django的新手,我正在尝试开发一个网站,用户可以在其中上传许多excel文件,然后将这些文件存储在媒体文件夹Webproject / project / media中。 然后,该文档会与它们上载的任何其他文档一起显示在列表中,你可以单击这些文档,它会显示有关它们的基本信息以及他们上载的excelfile的名称。从这里,我希望能够使用链接再次下载相同的excel文件: 我的网

  • 问题内容: 我希望站点上的用户能够下载路径被遮盖的文件,以便不能直接下载它们。 例如,我希望URL如下所示: http://example.com/download/?f=somefile.txt 在服务器上,我知道所有可下载文件都位于文件夹中。 有没有一种方法可以使Django提供该文件供下载,而不是尝试查找URL和查看以显示它? 问题答案: 对于“两全其美”,你可以将S.Lott的解决方案与x

  • 在我为客户制作的网站上,当他们尝试使用Internet Explorer 11下载文件时,他们无法从该站点下载文件。 这些文件保存在我们的服务器上,使用上传文件的数据库,位置,名称和MIME类型的文件能够被下载。例如,路径为“/uploaded _ files/6f/AE 69 BD 966 ba 4c 740 b 8073 ff 969 a 5425 b”,文件名为“Finland Test 1

  • 问题内容: 是否可以制作一个zip存档并提供下载,但仍不将文件保存到硬盘驱动器? 问题答案: 要触发下载,你需要设置标题: 如果你不想将文件放在磁盘上,则需要使用 你也可以选择设置标头:

  • 问题内容: 我希望站点上的用户能够下载路径被遮盖的文件,以便不能直接下载它们。 例如,我希望URL如下所示: http://example.com/download/?f=somefile.txt 在服务器上,我知道所有可下载文件都位于文件夹中。 有没有一种方法可以使Django提供该文件供下载,而不是尝试查找URL和查看以显示它? 问题答案: 你可以将的解决方案与模块结合使用:生成文件(或文件本