为什么文件上传后,打开文件提示已损坏?

721 阅读5分钟

前言

  • 常网IT源码上线啦!
  • 本篇录入技术选型专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
  • 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
  • 接下来想分享一些自己在项目中遇到的技术选型以及问题场景。

今天看了泰坦尼克号
你知道吗,我这辈子最幸运的事,就是赌赢了船票,然后遇见了你。

1.jpg

压力--

一、前言

今天像往常一样,开开心心的打代码编程。

突然产品说:现在上传后文件打开不了。

于是便有了今天这篇文章,一起来探讨一下。

当然,你也可以当做面试题。

二、回顾

想先回顾一下目前的上传功能的背景。

现有一个上传文件的需求,后台这边技术需要使用binary上传文件,postman如:

image.webp

那么axios怎么实现上传呢?

我们先来了解一下binary

三、binary

相当于Content-Type:application/octet-stream, 从字面意思得知,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以,一次只能上传一个文件。

四、代码实现

binary类型其实就是文件的File对象的类型。

一般来说:我们都是用FormData对象,把file对象添加进去。

设置Content-Type为:multipart/form-data

但其实我们使用FormData的时候,浏览器会自动设置为multipart/form-data。

image.webp

image.webp

export const postData= (params, data) => { return axios({
  method: 'post',
  url: `***`,
  params,
  data,
  headers: {
    'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq'
  }
}).then(res => res.data) };

const formData = new FormData();
formData.append("file", this.fileList[0].originFileObj) // 这里填入你的file文件对象

后台接收到了文件,也能保存到服务器内,但打开文件的时候,发现已经被损坏。

五、代码分析

我们来简单分析一下,我们使用

  1. content-type设置为: 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq'
  2. 数据要通过FormData去处理

后台也能接受到了。

但现在文件打不开。

后台人员用postman的binary形式,没有key的,而我们现在用FormData对象传过去是有key(file)的

后台拿到文件是拿到了,但get的时候如果是postman的形式应该直接拿到,可以理解为直接把obj给拿到了,而我们现在前端是obj.file,所以可能导致格式上出现了问题。

image.webp

六、解决方法

假设现在我们不知道postman的binary在代码中是怎么写的。

我们知道postman有可以用代码语言的示例:

image.webp

仔细看了一下:

没有使用formdata对象来包装,而是直接传入file对象(binary);

Content-Type貌似也没有设置。

image.webp

我们带着上面这两个,重新改一下我们的代码:

return Request({
  method: "put",
  url: `/url`,
  headers: {},
  maxBodyLength: Infinity,
  data: file
});

这样子的代码就代表postman的binary的传法。

浏览器打开后,发现我们的file对象没有在入参看到。

formdata的形式就会显示在入参这里。

image.webp

再尝试一下,发现文件上传成功了,附件也打开成功了。

后面查了一下jq的写法。

不额外处理file的值。

ebda72014b8f21fcd77fb5e68f5b89e.webp

七、额外知识

我们postman中 form-data、x-www-form-urlencoded、raw、binary有这么几个类型

image.webp

form-data:

在HTTP请求中,multipart/form-data 是一种常用的数据格式,它将表单数据组织成一条消息,通过标签和分隔符进行区分。

这种格式不仅支持上传键值对,还可以上传文件。当上传的字段包含文件时,会使用 Content-Type 指明文件类型,并通过 Content-Disposition 提供字段的相关信息。由于有 boundary 进行分隔,multipart/form-data 能够有效地同时上传多个文件和键值对,灵活性很高。

33.jpg

x-www-form-urlencoded:

application/x-www-form-urlencoded 是一种常见的HTTP数据格式,它将表单数据转换为键值对。例如,数据会被格式化为 name=java&age=23

这种格式适合简单的数据提交,通常用于标准的表单提交场景。每个键值对之间用 & 分隔,键和值通过 = 连接,使得解析变得简单高效。

raw

可以上传任意格式的文本,可以上传text、json、xml、html等

44.jpg

multipart/form-data与x-www-form-urlencoded区别:

multipart/form-data 格式能够上传文件等二进制数据,同时也支持表单键值对,最终会被整合成一条信息。

application/x-www-form-urlencoded 格式则仅限于上传键值对,且这些键值对之间用 & 符号分隔。这使得前者在处理多种数据类型时更为灵活。

至此撒花~

后记

我们在实际项目中或多或少遇到一些奇奇怪怪的问题。

自己也会对一些写法的思考,为什么不行🤔,又为什么行了?

最后,祝君能拿下满意的offer。

我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

小小导出,我大前端足矣!

靓仔,说一下keep-alive缓存组件后怎么更新及原理?

面试官问我watch和computed的区别以及选择?

面试官问我new Vue阶段做了什么?

前端仔,快把dist部署到Nginx上

多图详解,一次性啃懂原型链(上万字)

Vue-Cli3搭建组件库

Vue实现动态路由(和面试官吹项目亮点)

项目中你不知道的Axios骚操作(手写核心原理、兼容性)

VuePress搭建项目组件文档

原文链接

juejin.cn/spost/74169…