关于上传文件时文件类型(Content-type)值变化的问题

一、遇到的问题:

​ 最近在做一个上传Excel文件的功能时,遇到一个奇葩的问题:部分电脑可以上传,但是也有部分电脑上传不了。

​ 查来查去,最后发现是请求后台接口时的content-type的值不一致导致发生了这个问题。页面选中文件,前端使用Form表单提交方式,请求后端上传接口的时候请求头中的content-type值一直是application/octet-stream类型,正常情况下.xlsx文件的类型应该是application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,直接上图:

二、问题解决的过程:

先是百度查了一下content-type具体是个什么东东。

Content-Type:在HTTP协议消息头中,使用Content-Type来表示媒体类型信息。它被用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析html或仅仅展示一个文本等。

Post请求的内容放置在请求体中,Content-Type定义了请求体的编码格式。数据发送出去后,还需要接收端解析才可以。接收端依靠请求头中的Content-Type字段来获知请求体的编码格式,最后再进行解析。

问题猜想一:

​ 既然部分电脑上传的文件是application/octet-stream类型,那我上传文件的时候写死content-type的值不就解决了。

​ 实施后发现前端写死content-type的值之后所有电脑都不能上传文件了。。。(之前没有写死是因为表单提交浏览器会自动获取文件的类型)

为什么请求接口时写死content-type的值时后台会读不到文件?其实这里涉及到了springMVC的运行原理,可以参考下https://wwwblogs/kaiblog/p/7565231.html这篇文章,这里不做详细介绍。

问题猜想二:

​ 既然请求接口时文件类型为application/octet-stream,那在接口层面检测文件类型如果为application/octet-stream类型时不用去校验它直接上传文件。

public static final String[] CONTENT_TYPE_EXCEL = new String[] {"application/vnd.ms-excel", "application/octet-stream", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"};

在上传Excel文件中添加了application/octet-stream的文件类型,此时如果前端传入的文件类型为application/octet-stream就会直接上传文件(原本仅支持.xls和.xlsx类型的Excel文件)。

​ 至此,解决了部分电脑上传不了文件的问题。

问题猜想三:

​ 但是这里引入了新的问题,如果我在后台放松了文件类型的校验:加入application/octet-stream类型,这样其实是不严谨的,因为我本来就只支持上传.xls和.xlsx类型的Excel文件,此时加入了application/octet-stream类型的文件,我们知道浏览器获取不了该文件的真实类型时才会传application/octet-stream,就意味着如果是个word文件,浏览器若识别不了文件是个word文件,也会将content-type的值置为application/octet-stream,这样会使得后台对文件的校验相当于没有了校验。

​ 此时我有了这样的一个猜想:假如电脑上有了一个Excel的文件,但是没有能够打开Excel文件的工具,比如Office,此时是无法打开文件的,也是不知道文件的类型的,此时上传这种文件,浏览器是无法知道上传的文件是什么类型的文件。也就是说无法上传文件的那些电脑上安装的“工具”有问题!如何获知呢?

​ 查看电脑上是否安装了工具(比如office,wps,libaryOffice),你可以肉眼去看,但是提醒一句:眼睛是会骗人的!请往下看:

​ 如何在电脑中找到excel的注册表:打开注册表–HKEY_CURRENT_USER–SOFTWARE–Classes–MIME–Database–Content Type。

Content Type文件夹下的文件类型就是该电脑上支持的文件类型,只要保证正确的安装了打开Excel的工具,这些类型都是自动安装的,如果没有的话,解决方案有两个:

1、卸载电脑上的office重新安装(推荐,最安全,安装Office时会自动安装这些文件类型)

2、自己新建注册表

至此,解决文件上传时文件类型获取不到的问题。

更多推荐

关于上传文件Content-type值变化的问题