前端下载(jquery 踩坑记录)

最近在做一个功能,是调用一个后台接口实现excel表格下载的功能。后端返回的是文件流,前端采用的是jquery ajax。

记录一下整个思考过程,仅供参考。

接口调通之后,可以看到浏览器中返回值有内容,但是为乱码,同时ajax的success、error方法中没有打印出数据。
前端下载(jquery 踩坑记录)_第1张图片
网上查询看到,需要设置responseType,根据网上提示,修改代码为

$.ajax({
	url: "接口地址",
	type: "GET",
	dataType: 'JSON',
	contentType:"application/json;charset=UTF-8",
	async: true,
	data: params,
	xhrFields: {
		responseType: Blob
	},
	success: function(data) {
		console.log('success',data)
	}

经过修改后,提示responseText只支持类型为’’,或者类型为’text’
在这里插入图片描述
于是删除对responseType的设置,增加complete,进行状态查看。

complete: function(XMLHttpRequest, textStatus) {
    console.log(XMLHttpRequest,textStatus)
},

显示readyState 为4, “parsererror” ,查阅发现,因为后端返回的数据类型和前端请求中dataType的要求类型不一致。
解决方法:将dataType注释掉

此时

在ajax的success中没有打印出内容,但是在complete中的 responseText中可以看到乱码内容。查询得知,可以使用dataFilter对返回值进行预处理。
添加代码

dataFilter: function(data,type) {
    console.log('dataFilter',data,type)
    var result = new Blob(['\uFEFF'+ data], {type: 'text/plain;charset=utf-8'})
    return result
 }

此时success函数中终于可以打印返回的data了。

接下来开始实现下载:
方式1:

var reader = new FileReader();
reader.readAsDataURL(result);  // 转换为base64,可以直接放入a表情href
reader.readAsArrayBuffer(result)
reader.onload = function (e) {
	console.log('678',e.target.result)
	// 转换完成,创建一个a标签用于下载
	var downloadTag = document.createElement('a');
	downloadTag.download = 'data';
	downloadTag.href = e.target.result;
	downloadTag.id = 'yydownload';
	$("body").append(downloadTag);  
	// 修复firefox中无法触发click
	console.log(downloadTag)
	downloadTag.click()
	$(downloadTag).remove();
}

方式2

	const url = window.URL.createObjectURL(data)
	const link = document.createElement('a')
	link.href = url
	link.setAttribute('download', 'name')
	document.body.appendChild(link)
	link.click()
	console.log(link)

方式3

var params= {参数列表}
var form = $("
"); form.attr('style', 'display:none'); form.attr('target', ''); form.attr('method', 'get'); var url = '后台地址'; form.attr('action', url); $('body').append(form); for(let i in params) { var input = $(''); input.attr('type', 'hidden'); input.attr('name', i); input.attr('value', params[i]); form.append(input); } form.submit(); form.remove(); $('#downloadForm').remove();

直接报500,因为请求需要一个自定义请求头。

经过思考,认为是由于jquery自动把返回信息进行了转码,导致我即使在预处理阶段拿到的值都不是原始值,所以后续操作都在错误的基础上。

最终解决:

/* 原生ajax */
var str;
for(let i in params) {
	str = `${str}&${i}=${params[i]}`
}
console.log(str)
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.open("get",`/df/pay/businessbill/batchExportData.do?${str}`,true);
xhr.setRequestHeader('x-function-id',ip.getMenuId())
xhr.onreadystatechange=function(){
console.log('状态改变了')
if(xhr.readyState==4){
	if((xhr.status>=200 && xhr.status<300) || xhr.status==304){
		var blob = this.response;
		var url = window.URL.createObjectURL(blob);
		window.open(url)
		}else{
			alert("请求失败!");
		}
	}
};
xhr.send();

其他扩展:(未整理完整)

下载方式:

  • 下载
  • 前端请求接口,后端返回网络地址,前端使用浏览器打开即可实现下载。window.open(后端返回的地址) 或者window.location.href。(常用)。

FileReader

1 readAsArrayBuffer(file) 将文件读取为ArrayBuffer
2 readAsBinaryString(file) 将文件读取为二进制字符串
3 readAsDataURL(file) 将文件读取为Data URL
4 readAsText(file, [encoding]) 将文件读取为文本,encoding缺省值为'UTF-8'
5 abort() 终止文件读取操作
/*
    FileReader共有4种读取方法:
    1.readAsArrayBuffer(file):将文件读取为ArrayBuffer。
    2.readAsBinaryString(file):将文件读取为二进制字符串
    3.readAsDataURL(file):将文件读取为Data URL
    4.readAsText(file, [encoding]):将文件读取为文本,encoding缺省值为'UTF-8'
    5.abort()	终止文件读取操作
*/

前端本地读取excel
需要本地服务器

<body>
	<input type="file"onchange="read(this)" id="upload"/>
	<script type="text/javascript">
		function read(e){
			var file = document.querySelector("#upload").value
			// var files = tar.target.files[0];
			var fileReader = new FileReader();
			fileReader.onload = function(ev) {
				console.log(ev)
				var data = ev.target.result;
		        var wb;
		        wb = XLSX.read(btoa(fixdata(data)), {//手动转化
	                type: 'base64'
	            });
		        var persons = []; // 存储获取到的数据
		        var truckInfos = new Array() ;
		        persons = persons.concat(XLSX.utils.sheet_to_json(wb.Sheets["Sheet1"]));
				alert(1);
		        angular.forEach(persons,function(data,idx){
		      
		        });
			}
			// 以二进制方式打开文件
            // fileReader.readAsBinaryString(file);
            // fileReader.readAsArrayBuffer(file);
            fileReader.readAsText(file)
		}
		
	</script>
</body>

//字符串转字符串ArrayBuffer
function str2ab(s,f) {
var b = new Blob([s],{type:‘text/plain’});
var r = new FileReader();
r.readAsArrayBuffer(b);
r.onload = function (){if(f)f.call(null,r.result)}
}

			//ArrayBuffer转字符串
			function ab2str(u,f) {
				var b = new Blob([u]);
				var r = new FileReader();
				r.readAsText(b, 'utf-8');
				r.onload = function (){if(f)f.call(null,r.result)}
			}
var reader = new FileReader();
reader.readAsDataURL(result);  // 转换为base64,可以直接放入a表情href
// reader.readAsText(result)
reader.onload = function (e) {
console.log('678',e.target.result)
// 转换完成,创建一个a标签用于下载
var downloadTag = document.createElement('a');
downloadTag.download = 'data';
downloadTag.href = e.target.result;
downloadTag.id = 'yydownload';
$("body").append(downloadTag);  // 修复firefox中无法触发click
console.log(downloadTag)
downloadTag.click()
$(downloadTag).remove();
}
const link = document.createElement('a')
link.href = url
link.setAttribute('download', '7777')
document.body.appendChild(link)
link.click()
console.log(link)

文件读取

$('#yyid').change(function(e){
	var file = e.target.files[0];//获取文件
	var reader = new FileReader();
	reader.readAsArrayBuffer(file);
	reader.onload = function(e){
		let buffer = e.target.result  //此时是arraybuffer类型
		let hex = buf2hex(buffer)
		console.log(Object.prototype.toString.call (buffer) );
		// console.log(hex) //自行处理
		// console.log(Object.prototype.toString.call (hex) );
		const url = window.URL.createObjectURL(new Blob(['\uFEFF'+buffer], {type: 'text/plain;charset=utf-8'}))
		// const url =  window.URL.createObjectURL(hex);
		const link = document.createElement('a')
		link.href = url
		link.setAttribute('download', '5555555')
		document.body.appendChild(link)
		link.click()
}
	function buf2hex(buffer) { 
		// buffer is an ArrayBuffer
		return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
	}
})

jquery.form的ajaxsubmit提交时添加一个自定义头部header

你可能感兴趣的:(前端,菜鸡日记)