见标题。
网络上大部分都在说更改tomcat的web.xml中的MIME Type,但是下载是直接走的小文件系统,所以.. 说正题吧还是:
首先,现象:
1.curl 上传的文件doc,下载下来是doc
2.apache http Java api 上传的文件doc,下载下来是zip。
以下是我认为的原因,当你上传文件没有写明文件名,比如xxx.doc时,seaweedfs拿到这个文件了,但并不知道你下载这个文件的时候的response header应该给你什么。所以就默认了..
但是当你指明文件名的时候,小文件系统就知道你下载这个文件的时候,response header里要给你压上Content-Disposition: inline/attachement filename="xxx.docx",这个时候浏览器就知道该文件的MIME type了,就不会给你变成zip了...
文末有正解......
以下为apache http Java api 的对应代码:
httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(urlStr);
httpPost.setHeader(new BasicHeader("Accept-Language", "zh-cn"));
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.setCharset(Charset.forName("UTF-8"));
HttpEntity reqEntity = fileType.equals(MetadataType.DOC) || fileType.equals(MetadataType.DOCX)
|| fileType.equals(MetadataType.XLS) || fileType.equals(MetadataType.XLSX)
|| fileType.equals(MetadataType.PPT) || fileType.equals(MetadataType.PPTX)
? multipartEntityBuilder.
//声明为attachment
addBinaryBody(fileNameMd5, inputStream, ContentType.MULTIPART_FORM_DATA, fileNameMd5).build()
: multipartEntityBuilder.
//声明为inline
addBinaryBody(fileNameMd5, inputStream).build();
// 发起请求并返回请求的响应
httpPost.setEntity(reqEntity);
response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
再额外多说两居:
1.Multipart/form-data
我们都知道上传文件的使用,form表单的type要声明为Multipart/form-data.这个东西叫多部件form表单。为什么要叫多部件呢,
因为每一部分都可以有自己的Content-Type.Content-Desiposition.注意,这个不是request header里的,这个是Multipart/form-data里的。
------WebKitFormBoundary4Tiup80Sh4Qjiwdv
Content-Disposition: form-data; name="project_id" ps1556267447775
------WebKitFormBoundary4Tiup80Sh4Qjiwdv
Content-Disposition: form-data; name="group_id" ds1557727946676_165
------WebKitFormBoundary4Tiup80Sh4Qjiwdv
Content-Disposition: form-data; name="file"; filename="投资者关系活动记录表.doc"
Content-Type: application/msword
------WebKitFormBoundary4Tiup80Sh4Qjiwdv--
这个Multipart/form-data 就分为里三部分,每一部分都有自己的 Content-Disposition
最后一个声明里Content-Type,即声明了该文件的类型和浏览器的响应方式.
这里的content-type一般都是自动识别(根据上传的载体),不需要手动设置。
2.Content-Type
Content-Type: [type]/[subtype]; parameter
type 有下面的形式:
- Text:用于标准化地表示的文本信息,文本消息可以是多种字符集和或者多种格式的;
- Multipart:用于连接消息体的多个部分构成一个消息,这些部分可以是不同类型的数据;
- Application:用于传输应用程序数据或者二进制数据;
- Message:用于包装一个E-mail消息;
- Image:用于传输静态图片数据;
- Audio:用于传输音频或者音声数据;
- Video:用于传输动态影像数据,可以是与音频编辑在一起的视频数据格式。
subtype 用于指定 type 的详细形式。“type/subtype”配对的集合和与此相关的参数。下面是最经常用到的一些 MIME 类型:
- text/html(HTML 文档);
- text/plain(纯文本);
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" (for .docx files)
"application/vnd.openxmlformats-officedocument.wordprocessingml.template" (for .dotx files)
"application/vnd.openxmlformats-officedocument.presentationml.presentation" (for .pptx files)
"application/vnd.openxmlformats-officedocument.presentationml.slideshow" (for .ppsx files)
"application/vnd.openxmlformats-officedocument.presentationml.template" (for .potx files)
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" (for .xlsx files)
"application/vnd.openxmlformats-officedocument.spreadsheetml.template" (for .xltx files)
以下为部分http header 的内容。。 不过没啥软用
Accept:text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, image/apng, */*; q=0.8
作用:向服务器申明客户端(浏览器)可以接受的媒体类型(MIME)的资源
解释:浏览器可以接受 text/html、application/xhtml+xml、application/xml类型,通配符*/* 表示任意类型的数据。并且浏览器按照该顺序进行接收。( text/html —> application/xhtml+xml —> application/xml)
Accept-encoding: gzip, deflate, br
作用:向服务器申明客户端(浏览器)接收的编码方法,通常为压缩方法
解释:浏览器支持采用经过 gzip,deflate 或 br 压缩过的资源
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
作用:向服务器申明客户端(浏览器)接收的语言
解释:浏览器能够接受 en-US, en 和 zh-CN 三种语言,其中 en-US 的权重最高 ( q 最高为1,最低为 0),服务器优先返回 en-US 语言
延伸:语言与字符集的区别:zh-CN 为汉语,汉语中有许多的编码:gbk2312 等
以下为apache http Java api 的.. 正确使用,这个才更像是一个MultipartEntity
MultipartEntity multipartEntity = new MultipartEntity();
multipartEntity.addPart("name", new StringBody("aaa"));
//这里的image 应该没啥意义吧.. 就好比Mlutipart文件上传时的参数对应
multipartEntity.addPart("image", new InputStreamBody(new FileInputStream(new File("D:/httpclient/images/0.jpg");), file.getName()));
multipart/form-data与application/x-www-from-urlencoded(默认)区别
- multipart/form-data:既可以上传二进制数据,也可以上传表单键值对,只是最后会转化为一条信息
- x-www-from-urlencoded:只能上传键值对,并且键值对都是间隔分开的。