本文由 千趣源码 – qianqu 发布,转载请注明出处,如有问题请联系我们!txt文档乱码怎么修复-手机txt文件打开乱码修复方法
在Web开发设计流程中,坚信大家都遇到过配件免费下载的情景,在其中,各种各样浏览器下载后中文乱码文件夹名称的难题很有可能困惑了大伙儿一段时间。
在网络上检索,绝大多数全是根据Request Headers中的UserAgent字段名来分辨电脑浏览器种类,并依据不一样的电脑浏览器做不一样的解决,类似下边的编码:
// MicroSoft Browserif (agent.contains("msie") || agent.contains("trident") || agent.contains("Edge")) { // filename 独特解决}// Firefoxelse if (agent.contains("firefox")) { // filename 独特解决}// safarielse if (agent.contains("safari")) { // filename 独特解决}// chromeelse if (agent.contains("chrome")) { // filename 独特解决}// 别的else{ // filename 独特解决}//最终把独特解决后的文件夹名称放进head里resPONse.seTheader("Content-Disposition", "attachment;fileName=" filename);殊不知,这一段编码看上去很奇妙。为何每一个电脑浏览器处理方法不一样?每一次建立新电脑浏览器都务必兼容吗?难道说沒有统一的规范来限定这种电脑浏览器吗?
带上这些疑惑,我查询了RFC文本文档,最后想到了一个雅致的解决方法:
// percentEncodedFileName 为百分号编号后的文件夹名称response.setHeader("Content-disposition", "attachment;filename=" percentEncodedFileName ";filename*=utf-8''" percentEncodedFileName);通过检测,这一回应头能够兼容&144;售市场上全部主流浏览器。因为它归属于HTTP协议书,因此与语言表达不相干。只需安装这种标准设定回应头,配件名字烦人的中文乱码难题就能一劳永逸地处理。
在下一课堂,意味着将带您到茧,并根据阅读文章RFC文本文档来修复此回应头的导出全过程。
1.內容-处理
一切都需5201;从RFC 6266逐渐。在本文本文档中,引进了內容处理回应文章标题。实际上,它不属于HTTP规范,但它在本文本文档中受限制,因为它被普遍应用。其英语的语法形式如下所示:
content-disposition = "Content-Disposition" ":" disposition-type *( ";" disposition-parm ) disposition-type = "inline" | "attachment" | disp-ext-type ; case-insensitive disp-ext-type = token disposition-parm = filename-parm | disp-ext-parm filename-parm = "filename" "=" value | "filename*" "=" ext-value有二种个性特征:
inline 意味着默认设置解决,一般会在网页页面展现attachment 意味着应当被储存到当地,必须相互配合设定filename或filename*一定要注意disposition-parm中的文件夹名称和文件夹名称*。文档要求我们的内容能够用以储存的文件夹名称。
4046;别取决于文件夹名称的值沒有编号,而文件夹名称*遵循RFC 5987中界定的编码规则:
Producers MUST use either the "UTF-8" ([RFC3629]) or the "ISO-8859-1" ([ISO-8859-1]) character set.因为filename*是之后界定的,很多旧电脑浏览器不兼容,文本文档要求当二者与此同时发生在文章标题字段名时,应当应用filename*而忽视filename。
这时,回应头的结构早已突显,摘抄[RFC 6266]中的实例如下所示:
Content-Disposition: attachment; filename="EURO rates"; filename*=utf-8''€ rates在这儿,大家将表述filename * = utf-8 " % E2 % 82% AC % 20 rates,乍一看好像很怪异。它事实上是用反斜杠做为分节符,把等于号右侧分为三一部分:第一部分是字段名(utf-8),正中间一部分是语言表达(未添充),最终一部分是% e2% 82% ac% 20。这一部分的构成在RFC 2231中有详细描述。第4节:
A single quote is used to separate the character set, language, and actual value information in the parameter value string, and an percent sign is used to flag octets encoded in hexadecimal.2.百分数编号
百分数编号也称之为百分数编号或网站地址编号。
如上所述,filename*遵循[RFC 5987]中界定的编码规则,务必适用的字段名在[RFC 5987] 3.2中界定:
recipients implementing this specificationMUST support the character sets "ISO-8859-1" and "UTF-8".除此之外,[RFC 5987] 3.2.1要求百分位数编码合乎RFC 3986 .第2.1节中的界定,摘抄如下所示:
A percent-encoding mechanism is used to represent a data octet in acomponent when that octet's corresponding character is outside theallowed set or is being used as a delimiter of, or within, thecomponent. A percent-encoded octet is encoded as a charactertriplet, consisting of the percent character "%" followed by the twohexadecimal digits representing that octet's numeric value. Forexample, " " is the percent-encoding for the binary octet"00100000" (ABNF: %x20), which in US-ASCII corresponds to the spacecharacter (SP). Section 2.4 describes when percent-encoding anddecoding is APPlied.一定要注意,[RFC 3986]明文规定空帧将根据百分号编号为 。
在另一份文档《RFC 1866 .第8.2.1节表单-URL编码媒体类型》中,要求:
The default encoding for all forms is `application/x-www-form- urlencoded'. A form data set is represented in this media type as follows: 1. The form field names and values are escaped: space characters are replaced by ` ', and then reserved characters are escaped as per [URL]这儿,在application/x-www-form-URL encoded种类的信息中,空应当更换为 ,别的标识符依照【URL】中的界定开展转义,在其中【URL】偏向RFC 1738,其修订本中与URL有关的全新文本文档恰好是【RFC 3986】。
这就是为何很多参考文献叙述空的百分位数编号結果为 或 ,比如:
w3schools:URL编码一般用减号( )或 替换空格。
MDN:依据前后文的不一样,标识符“”被译成“ ”(如同在application/x-www-form-URL encoded信息中采用的百分数编号版本号一样),或是是在URL上应用的“ ”文件格式。
那麼那么问题来了。在研发流程中,大家应当如何处理空网格图标识符的百分数编号?
班集体意味着提议大伙儿遵循全新的文本文档,由于[RFC 1866]中界定的状况只适用application/x-www-form-URL encoded种类,就学分制编号的界定来讲,大家应当以[RFC 3986]为规范,因此不管哪儿必须学分制编号,都需要将空的学分制编号为 。在stackoverflow上,也有一个回答能够适用这一见解:何时把空格符编号成减号( )或% 20?
3.编码实践活动。
拥有理论基础,编码当然写出去,编码立即写出去:
@GETMapping("/downloadFile")public String download(String serverFileName, httpservletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("utf-8"); response.setContentType("application/octet-stream"); String clientFileName = fileService.getClientFileName(serverFileName); // 对真正文件夹名称开展百分号编号 String percentEncodedFileName = URLEncoder.encode(clientFileName, "utf-8") .replaceAll("\ ", " "); // 拼装contentDisposition的值 StringBuilder contentDispositionValue = new StringBuilder(); contentDispositionValue.append("attachment; filename=") .append(percentEncodedFileName) .append(";") .append("filename*=") .append("utf-8''") .append(percentEncodedFileName); response.setHeader("Content-disposition", contentDispositionValue.toString()); // 将文件流提到response中 try (InputStream inputStream = fileService.getInputStream(serverFileName); OutputStream outputStream = response.getOutputStream() ) { IOUtils.copy(inputStream, outputStream); } return "OK!";}编码比较简单,有二点必须表述:
URLEncoder.encode(clientFileName, “utf-8”)方式以后,为何还需要.replaceAll(“\ ”, “ ″)。如同前文上述,大家早已确立,一切必须百分号编号的地区,都应当把 空格符编号为 ,而URLEncoder这一类的表明上确立标明其会将空格符变换为 :The space character ” ” is converted into a Plus sign “{@code }”.实际上这并不怨 JDK,因为它的备注名称里表明了其遵循的是application/x-www-form-urlencoded( PHP 中也有那么一个涵数,也是那么个招数)Translates a string into {@code application/x-www-form-urlencoded} format using a specific encoding scheme. This method uses the因此这儿大家用.replaceAll(“\ ”, “ ”) 把 号解决一下,使其符合实际 [RFC 3986] 的百分号编号标准。这儿是为了便于表明难题,把所有的实际操作都呈现出来。自然,你彻底能够自身完成一个PercentEncoder类,丰俭由人。[RFC 6266] 规范中filename=的value是不用编号的,这儿的filename=后边的 value 为何要百分号编号?回望 [RFC 6266] 文本文档, filename和filename*与此同时发生时取后面一种,电脑浏览器太老不兼容新标准时取前面一种。现阶段主要的电脑浏览器都选用自升2026;对策,因此绝大多数都适用新标准——除开老版本IE。老版本的IE对 value 的解决对策是 开展百分号编解码 并应用。因此这儿专业把filename=的value开展百分号编号,用于兼容老版本 IE。PS:学习委员评测 IE11 及 Edge 早已适用新标准了。4.浏览器测试。
依据下面的图statcounter统计分析的2019年我国市场电脑浏览器占用量,学习委员设计方案了一个包括汉语,英语和空的文件夹名称开展下载测试。检测用txt。
检测結果:BrowserVersionpassChrome84.0.4147.125trueUCV6.2.4098.3trueSafari13.1.2trueQQ Browser10.6.1(4208)trueIE7-11trueFirefox79.0trueEdge44.18362.449.0true360安全浏览器1212.2.1.362.0trueEdge(chromium)84.0.522.59true从检测結果看来,基本上兼容销售市场上全部主流浏览器。
5.引言
回过头来再看本文的內容,实际上是电脑浏览器兼容问题造成的配件名字错码。为了更好地彻底解决这个问题,查看了二种标准文件:
HTTP 回应头有关规范[RFC 6266],[RFC 1866]编码方式[RFC 5987],[RFC 2231],[3986],[1738]以【RFC 6266】为起始点,大家全篇引入了6篇【RFC】-有关参考文献,均未注明来源。有兴趣的同学们能够依据文章内容的构思阅读文章初始文本文档,相信你会对这个问题有深入的了解。编码已上传入GitHub。
最终禁不住感慨:标准真的是好产品。它如同Java语言中的插口。只制订规范,实际实行交给大伙儿玩儿。







