记一次文件因content-type问题无法打开的经历

news2025/1/15 19:43:03

记一次文件因content-type问题无法打开的经历

  • 场景
  • 方案
    • Jsoup的Content-Type
    • simplemagic
    • file can't open
    • 流不可重复消费问题
    • Tika
  • 总结

在Http请求头和响应头都有这个attribute,来声明请求和响应报文的资源类型。

Content-Type(MediaType),即是Internet Media Type,互联网媒体类型,也叫做MIME类型。在互联网中有成百上千中不同的数据类型,HTTP在传输数据对象时会为他们打上称为MIME的数据格式标签,用于区分数据类型。最初MIME是用于电子邮件系统的,后来HTTP也采用了这一方案。
在HTTP协议消息头中,使用Content-Type来表示请求和响应中的媒体类型信息。它用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析并展示html等等。

场景

我这边遇到的情况是,源文件的Content-Type全都显示为application/octet-stream,如PDF,PNG等,都显示这个,接着我们需要将这个文件上传到下游系统中,下游系统有另外的retrieve接口,来查看和下载这些文件。按照原逻辑,上传到下游系统的文件的Content-Type依旧会显示为application/octet-stream,部分终端使用这种格式下载下来是没什么问题的,能正确获取文件名,也能正常打开。问题出在某些终端对文件扩展名的解析方式不一样,通过mimeType去解析文件时,遇到application/octet-stream就会有问题,文件名可能就变成了xxx.bin。当然,这并不是我们所期望的。

方案

从源文件到下游系统,中间由我们系统集成,所以很理所当然想到在上传到下游系统之前,能否把这个Content-Type给它弄对。

Jsoup的Content-Type

查看了源代码,我们系统在上传文件到下游系统时,使用的是Jsoup三方依赖。这个接口需要同时上传文件和json文本,请求方式为POST。

文本参数用典型的kv参数方法

/**
     * Add a request data parameter. Request parameters are sent in the request query string for GETs, and in the
     * request body for POSTs. A request may have multiple values of the same name.
     * @param key data key
     * @param value data value
     * @return this Connection, for chaining
     */
    Connection data(String key, String value);

针对文件类型的参数,Jsoup提供了以下方法,可以设定文件名和文件输入流

    /**
     * Add an input stream as a request data parameter. For GETs, has no effect, but for POSTS this will upload the
     * input stream.
     * @param key data key (form item name)
     * @param filename the name of the file to present to the remove server. Typically just the name, not path,
     * component.
     * @param inputStream the input stream to upload, that you probably obtained from a {@link java.io.FileInputStream}.
     * You must close the InputStream in a {@code finally} block.
     * @return this Connections, for chaining
     * @see #data(String, String, InputStream, String) if you want to set the uploaded file's mimetype.
     */
    Connection data(String key, String filename, InputStream inputStream);

同时,我注意到Jsoup还提供了另外一个上传文件的方法,该方法支持设置文件的Content-Type

    /**
     * Add an input stream as a request data parameter. For GETs, has no effect, but for POSTS this will upload the
     * input stream.
     * @param key data key (form item name)
     * @param filename the name of the file to present to the remove server. Typically just the name, not path,
     * component.
     * @param inputStream the input stream to upload, that you probably obtained from a {@link java.io.FileInputStream}.
     * @param contentType the Content Type (aka mimetype) to specify for this file.
     * You must close the InputStream in a {@code finally} block.
     * @return this Connections, for chaining
     */
    Connection data(String key, String filename, InputStream inputStream, String contentType);

simplemagic

看到这里,我喜出望外,认为只需要根据源文件的inputStream来获取文件的Content-Type,设置到这个参数里就行了。在获取inputStream的Content-Type信息时,有很多选择,有原生的,也可以选择三方依赖,我这里选择的是simplemagic。

<dependency>
    <groupId>com.j256.simplemagic</groupId>
    <artifactId>simplemagic</artifactId>
    <version>1.17</version>
</dependency>

通过以下代码即可获取文件的Content-Type对象

ContentType contentType = new ContentInfoUtil().findMatch(file).getContentType();

该框架对输入提供了良好的支持,可以是文件路径,文件对象,文件流,也可以是byte数组。
在这里插入图片描述
按照这个思路,很快就完成了修改,本地postman测试,很快通过。

file can’t open

然而,按照上面描述的改动发版后,从下游系统下载的文件却无法打开。

通过postman调用下载接口,返回的内容可以预览(pdf格式,不得不说postman很强大),但是save response to file过后,文件却无法打开。这里有个小妙招,也是在工作中遇到的,有些打不开的pdf文件,如果使用类如edge等浏览器直接打开,打不开的话就直接报错打不开,如果用adobe尝试打开失败的话,会提示一些打不开的原因,如文件加密,文件格式损坏,文件破损等。这里我通过adobe打开发现是文件的file type有问题。
在这里插入图片描述

到这里,我怀疑过是我们下载接口的问题,但测试过直接从下游系统下载文件,文件依旧无法打开,那么问题只能出在我们将文件上传到下游系统的过程了。

我怀疑过Jsoup的传参方式是否正确,尝试过在文件头信息中加入Content-Type(因为我在debug的时候,看到入参的文件流是有头信息的,如postman上传,客户端上传等,都有),构建临时文件来转换等方法,均无一成功。首先,明确的是,通过simplemagic获取到的mimeType是对的,传到下游系统再反查出来回写到响应头里面的也是对的。

流不可重复消费问题

在处理文件打不开的过程,其实花费了许多时间,尝试的方式也很多,在上面没有一一列举。从下游系统下载的文件,通过simplemagic查看其Content-Type信息,为unkonwn,但文件后缀名是对的。这里需要说明一下,文件的mimeType判断方式有多种,扩展名是最常见也是不一定靠谱的一种。比如你创建一个text文件,强行将其扩展名修改为.pdf,再打开就会报错了,而且报的错和我这次遇到的报错一模一样。
在这里插入图片描述

在历经层层磨难后,终于发现了问题所在。

一个inputStream对象,我为了传获取它的Content-Type,其实已经消费了一次,在通过Jsoup上传到下游系统时,还是使用的是原来的那个流。再消费了一次后,再通过simplemagic去解析相同流的Content-Type时,你会发现结果就是unkonwn(第二次消费时,并没有报文件已关闭之类的异常)。至此,文件打不开的问题,就转换为处理流重复消费的问题了。直接跳转到针对流只能消费一次的处理方案就可以了,之前已经记录过,不再赘述。

通过这里的修改,文件便可以正常的上传,下载,预览,打开了。

Tika

和simplemagic类似,tika也是一个文件Content-Type解析的三方依赖,在处理问题的过程中,我也用过。经过测试,simplemagic对大部分文件支持良好,但csv文件却不行,而tika可以解析csv,但对office相关文件显得有些无能为力。所以最终使用二者结合来支持文件mimeType的判断。

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>2.8.0</version>
</dependency>

总结

简单总结一下,在你我的开发生涯中,总会遇到一个又一个麻烦的问题(对当时的你会是个麻烦),可能你花了一些时间能够处理,并在过程中有所收获,也有可能你直接百度或csdn一搜就有了结果。领导可能在意的是处理了问题的结果,而对你个人成长,更重要的是处理问题的过程。

在刚出来工作的第一家公司,我们的一个服务总是会内存溢出,可用性极差。真正处理要处理这个问题可能需要花很多时间去排查测试(因为已经排查过业务代码的逻辑),领导建议做服务自动重启的工作,这样在一定程度能够缓解。对要求不算高的甲方,可能就糊弄过去了。但作为一个有洁癖的程序员,肯定不能接受这种是是而非的处理方式。后来通过层次排查,发现问题出来了三方依赖里面,问题才得到了真正的处理。

类似这样的问题还有很多,我也在CSDN的问答板块看到过许许多多折磨这程序员的问题,有些我已经经历过并掌握了,会觉得很简单,有一些是我还没曾在学习过程或项目中遇到过的,当我遇到了,也会头疼。所以,不断总结就显得非常重要了。

另外相对自己告诫的一点,查看处理问题时眼光不能太局限,定位问题比处理问题更重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/885421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你真的了解数据结构与算法吗?

数据结构与算法&#xff0c;是理论和实践必须紧密结合的一门学科&#xff0c;有关数据结构和算法同类的课程或书籍&#xff0c;有些只是名为“数据结构”&#xff0c;而非“数据结构与算法”&#xff0c;它们在内容上并无很大区别。 实际上&#xff0c;数据结构和算法&#xf…

有哪些前端开发工具推荐? - 易智编译EaseEditing

在前端开发中&#xff0c;有许多工具可以帮助你更高效地进行开发、调试和优化。以下是一些常用的前端开发工具推荐&#xff1a; 代码编辑器/集成开发环境&#xff08;IDE&#xff09;&#xff1a; Visual Studio Code&#xff1a;功能强大、轻量级的代码编辑器&#xff0c;支…

富士胶片 : 柯达倒下了,我们凭什么屹立不倒

当整个行业被新技术颠覆后&#xff0c;其中的领军企业如何才能活下去? 富士胶片在面临行业被颠覆的情况下&#xff0c;迅速调整策略&#xff0c;果断裁减传统业务、大规模投资新兴领域&#xff0c;体现出敏捷的链节竞争优势。这使得富士胶片在数码时代来临之际&#xff0c;能…

MATLAB高分辨率图片

把背景调黑&#xff0c;把曲线调黄&#xff0c;把grid调白&#xff0c;调调字体字号的操作 close all a0:0.1:10; noise2*rand(1,length(a)); bsin(a)sin(3*a)noise;plot(a,b,y,linewidth,2); ylim([-3 4]) %y轴范围 set(gca,xgrid,on,ygrid,on,gridlinestyle,-,Grid…

01.在实战中提升自己----表达式解析

1.我们面临的问题与挑战 我的工作成功就是交付可用产品&#xff0c;而且是要满足超大规模企业应用的产品。在实践过程中&#xff0c;不管我们是处于哪个阶段&#xff0c;交付的内容就是会大规模应用的工具。在我们的面前&#xff0c;要不提供完善的支持配套&#xff0c;要不投…

云安全攻防(十二)之 手动搭建 K8S 环境搭建

手动搭建 K8S 环境搭建 首先前期我们准备好三台 Centos7 机器&#xff0c;配置如下&#xff1a; 主机名IP系统版本k8s-master192.168.41.141Centos7k8s-node1192.168.41.142Centos7k8s-node2192.168.41.143Centos7 前期准备 首先在三台机器上都执行如下的命令 # 关闭防火墙…

H3C QoS打标签和限速配置案例

EF&#xff1a;快速转发 AF&#xff1a;确保转发 CS&#xff1a;给各种协议用的 BE&#xff1a;默认标记(尽力而为) VSR-88-2 出口路由配置&#xff1a; [H3C]dis current-configuration version 7.1.075, ESS 8305 vlan 1 traffic classifier vlan10 operator and if-match a…

车规级半导体分类(汽车芯片介绍)

车规级半导体&#xff0c;也被称为“汽车芯片”&#xff0c;主要应用于车辆控制装置、车载监控系统和车载电子控制装置等领域。这些半导体器件主要分布在车体控制模块上&#xff0c;以及车载信息娱乐系统方面&#xff0c;包括动力传动综合控制系统、主动安全系统和高级辅助驾驶…

Centos7安装docker后默认开启docker0的网卡|卸载默认网卡

一&#xff1a; 停掉服务 systemctl stop docker [rootwww ~]# systemctl stop docker [rootwww ~]# systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor prese…

总结 TCP 协议的相关特性

TCP协议段格式: 如图, 端口号: 是其中一个重要的部分,知道端口号才能确认数据交给哪个应用程序(端口号属于传输层的概念). 4位首部长度:4bit表示的范围是0->15,在此处,单位是"4字节",因此,将这里的数值 * 4&#xff0c;才是真正的报头长度,即TCP 报头最大长度,60…

CentOS系统环境搭建(十二)——CentOS7安装Elasticsearch

centos系统环境搭建专栏&#x1f517;点击跳转 CentOS 7.9 安装 Elasticsearch 7.17.12 文章目录 CentOS 7.9 安装 Elasticsearch 7.17.121.下载2.上传3.解压4.调整es占用内存5.修改elasticsearch配置文件6.创建用户7.Elasticsearch 后台启动与关闭 1.下载 &#x1f517;http…

XXL-JOB学习笔记——调度中心

集群部署配置 3.1.服务启动 XXL-JOB的集群部署非常简单&#xff0c;只需要注意两点&#xff1a; 集群节点都连接的是同一个数据库。 多台机器部署时&#xff0c;需要统一系统时间&#xff0c;如果是单个机器部署&#xff0c;则不用管这条。 现在是在同一台机器中&#xff0c;…

W5100S-EVB-PICO做UDP Client进行数据回环测试(八)

前言 上一章我们用开发板作为UDP Server进行数据回环测试&#xff0c;本章我们让我们的开发板作为UDP Client进行数据回环测试。 连接方式 使开发板和我们的电脑处于同一网段&#xff1a; 开发板通过交叉线直连主机开发板和主机都接在路由器LAN口 测试工具 网路调试工具&a…

神采PromeAI,设计师的高效创作搭子

2023年&#xff0c;没有一个打工人不关注AI&#xff0c;也没有一个老板不想乘上AI东风、革新行业的梦。在生成式AI的可控性越强&#xff0c;对市场和产业的颠覆性就越大&#xff01; 神采PromeAI的可控性得到许多用户的认可&#xff0c;网站已上线草图渲染、照片转线稿、涂抹替…

UDP数据报结构分析(面试重点)

在传输层中有UDP和TCP两个重要的协议&#xff0c;下面将针对UDP数据报的结构进行分析 UDP结构图示 UDP报头结构的分析 UDP报头有4个属性&#xff0c;分别是源端口&#xff0c;目的端口&#xff0c;UDP报文长度&#xff0c;校验和&#xff0c;它们都占16位2个字节&#xff0c;所…

CSS自己实现一个步骤条

前言 步骤条是一种用于引导用户按照特定流程完成任务的导航条&#xff0c;在各种分步表单交互场景中广泛应用。例如&#xff1a;在HIS系统-门诊医生站中的接诊场景中&#xff0c;我们就可以使用步骤条来实现。她的执行步骤分别是&#xff1a;门诊病历>遗嘱录入>完成接诊…

福昕阅读器文档无法高亮的问题 转

转自福昕阅读器文档无法高亮的问题_福昕pdf高亮用不了_没有价值的生命的博客-CSDN博客 最近在阅读一篇PDF文档时&#xff0c;对一些内容进行高亮时&#xff0c;发现不能够进行高亮&#xff0c;然后通过在网上查找解决方法算是解决了我的问题。下面我将总结2点不能进行注释的情…

无涯教程-Perl - sqrt函数

描述 此函数返回EXPR的平方根&#xff1b;如果省略,则返回$_。大多数情况下,此函数返回浮点数。 语法 以下是此函数的简单语法- sqrt EXPRsqrt返回值 该函数返回浮点数。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl -w$resultsqrt(4); print " sqrt(4) …

2024第12届国际生物发酵展,3月6-8日济南举办

2024第12届国际生物发酵产品与技术装备展&#xff08;济南展&#xff09; 2024年3月6-8日 | 山东国际会展中心 2024第13届国际生物发酵产品与技术装备展&#xff08;上海展&#xff09; 2024年8月7-9日 | 上海新国际博览中心 主办单位&#xff1a; …

采用nodejs+vue语言和mysql汽车4s店服务管理系统 _od8k

为设计一个安全便捷&#xff0c;并且使用户更好获取本汽车服务信息&#xff0c;本文主要以安全、简洁为理念&#xff0c;实现用户快捷寻找汽车服务信息&#xff0c;从而解决汽车服务信息复杂难辨的问题。该系统以vue架构技术为基础&#xff0c;采用nodejs语言和mysql数据库进行…