今天遇到一个excel下载乱码问题,从服务器上使用流下载方式,用jquery.ajax下载之后,再转成blob使用虚拟节点下载客户端。然后一直乱码。找了很多方法,包括服务器指定 response.setCharacterEncoding(“utf-8”); 客户端再使用 charset=utf-8 指定编码。再或者从 ms-excel 到修改为 octet-stream ,各种组合都无效。烦了一下午。终于找到了一篇博客 jQuery的ajax下载blob文件 ,很显然这篇博客被抄来抄去。也就不转载了,自己搜吧以后。这篇博客提供了一个思路,ajax在底层自动将数据转型为字符串,而且编码不被控制。这也就是为什么我自己制定编码都无效的原因,因为我没有指定ajax底层的编码方式。
旧代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | $.ajax({type: method,
 data: JSON.stringify(data),
 url: "http://localhost:8096" + url,
 headers: {
 'Content-Type': 'application/json'
 }
 }).done(function (data, status, jqXHR) {
 console.log(data instanceof Blob);
 var reader = new FileReader();
 reader.readAsText(new Blob([data]), 'utf-8');
 reader.onload = function (evt) {
 console.log(evt);
 const url = window.URL.createObjectURL(new Blob(['\uFEFF' + evt.target.result], {type: 'application/ms-excel;charset=utf-8'}));
 const link = document.createElement('a');
 link.href = url;
 link.setAttribute('download', '名片印刷导出.xls');
 document.body.appendChild(link);
 link.click();
 URL.revokeObjectURL(link.href);
 document.body.removeChild(link);
 };
 });
 
 | 
  本着这个思路,就用 XMLHttpRequest 替代掉了 ajax ,没想到马上就解决了。真的是坑
有效的代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 
 | var url = "/businessCard/excelBusinessCard";var method = "POST";
 var data = {
 "applicantId": getUserId(),
 "pageNo": 1,
 "pageSize": 10000
 };
 data.token = getToken();
 var xhr = new XMLHttpRequest();
 xhr.open('POST',  "http://localhost:8096" + url, true);
 xhr.setRequestHeader("Content-Type", 'application/json');
 xhr.responseType = "blob";
 
 xhr.onload = function () {
 
 if (this.status === 200) {
 
 var blob = this.response;
 var reader = new FileReader();
 reader.readAsDataURL(blob);
 reader.onload = function (e) {
 
 var a = document.createElement('a');
 a.download = 'data.xls';
 a.href = e.target.result;
 $("body").append(a);
 a.click();
 $(a).remove();
 }
 }
 };
 
 xhr.send(JSON.stringify(data));
 
 |