后台二进制文件 在前台下载方法总结

こ雲淡風輕ζ 提交于 2020-02-27 01:50:35

总结下实际开发过程中使用过的文件下载方法:

刚开始接触$.ajax()时 欣喜若狂,以为所有的异步交互都可以用它来操作,直到流文件。具体的场景是:

  • 后台操作文件 ,以二进制流的形式,返回到前台(我实际的场景是导出Excel文件)
  • context.Response.BinaryWrite(二进制数组);

首先想到的是通过$.ajax来进行操作,因为和后台交互的参数很多,它的参数形式可以用键值对对象的形式,很方便,

但是怎么操作都不行,不报错,但是文件就是不能下载,又想到设置dataType的形式,发现没文件流的形式,心中

一万个…….

废话少说,总结方法:

(1)通过a标签的形式,应该可以满足大多的需求。

就是通过设置href属性,点击a标签,就可以下载成功。PS:a的html5中download的属性,可以直接重命名文件。

  • 固定的:<br><a   download="data.xls" href="file.ashx?paramone=canshuyi">   </a><br>动态的:
<button type="button"  onclick="download()">导出</button>
function download() {
    var a = document.createElement('a');
    var url = 'download/?filename=aaa.txt';
    var filename = 'data.xlsx';
    a.href=url;
    a.download = filename;
    a.click()
}


 (2)通过window.location

  • window.location = "../handler/OperateExcel/OutExcelCom.ashx?tablename=canshuyi"

 (3)创建iframe

var elemIF = document.createElement("iframe");
elemIF.src = "../lib/TemplateCollection/" + ExcelName + ".xls";
elemIF.style.display = "none";
document.body.appendChild(elemIF);


 以上三种方法指向后台返回文件流的方法,或者具体的实际文件路径,都可以下载文件。

(4)HTML5中blob对象
很多人都在说第这种方法可以满足,其实是错误方式

<button type="button"  onclick="download()">导出</button><br>
function download() {
    var url = 'download/?filename=aaa.txt';
    $.get(url, function (data) {
        console.log(typeof(data))
        blob = new Blob([data])
        var a = document.createElement('a');
        a.download = 'data.xlsx';
        a.href=window.URL.createObjectURL(blob)
        a.click()
    })
}


 这种方式保存的文件是不能打开的,console.log(typeof(data))会看到是string类型(乱码的),原因是jquery将返回的数据转换为了string,不支持blob类型。

正确方式:

<button type="button"  onclick="download()">导出</button><br>
function download() {
    var url = 'download/?filename=aaa.txt';
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);        // 也可以使用POST方式,根据接口
    xhr.responseType = "blob";    // 返回类型blob
    // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
    xhr.onload = function () {
        // 请求完成
        if (this.status === 200) {
            // 返回200
            var blob = this.response;
            var reader = new FileReader();
            reader.readAsDataURL(blob);    // 转换为base64,可以直接放入a表情href
            reader.onload = function (e) {
                // 转换完成,创建一个a标签用于下载
                var a = document.createElement('a');
                a.download = 'data.xlsx';
                a.href = e.target.result;
                $("body").append(a);    // 修复firefox中无法触发click
                a.click();
                $(a).remove();
            }
        }
    };
    // 发送ajax请求
    xhr.send()
}

实际中碰到的一种情况是:

  • 没有抛出异常的情况下,返回的数据流的type为:application/xml
  • 如果抛出异常,那么返回的数据流的type为:text/html

Action代码:

if(inputStream != null)
		fileLength=inputStream.available();
	else
		fileLength=0;

	String method=request.getMethod();
	String userAgent=request.getHeader("User-Agent");
	Browser browser=Browser.fromUserAgent(userAgent);
	this.contentType=FileContentType.buildContentType(filename);
	if("POST".equals(method))
	{
		filename=URLEncoder.encode(filename, "UTF-8");
	}
	else
	{
		switch(browser.getType())
		{
		case Browser.IE:
			filename=URLEncoder.encode(filename, "UTF-8");
			break;
		default:
			filename=new String(filename.getBytes(),"ISO8859-1");
			break;
		}
	}
	
	this.contentDisposition="attachment;";				
	this.contentDisposition+="filename=\""+filename+"\"";

	response.setHeader("accept-ranges", "bytes");

xml配置:

<action name="importAndExportDownload" class="cost-importAndExportAction"
			method="download">
	<result type="stream">
		<param name="contentDisposition">${contentDisposition}</param>
		<param name="contentType">${contentType}</param>
			<param name="inputName">inputStream</param>
	</result>
</action>

后台返回正常的文件流:直接下载

后台抛出异常throw new exception,获取错误信息,并且用easyui的dialog对话框展示:

错误信息也是流的形式返回,数据格式内容示例如下:

"<html>
<body bgcolor="white">
<span class="bold">备份文件大小异常,可重新尝试备份操作!文件大小:6291 检测最小值:700000<br></span>
</body>
</html>
{"data":null,"dataFieldList":[],"dataMap":[],"message":"备份文件大小异常,可重新尝试备份操作!文件大小:6291 检测最小值:700000<br>","returnCode":-20000000}"

JS代码:

function postDownload(url){
	var request = new XMLHttpRequest();
	request.open("POST", url);
	request.responseType = "blob"; // 返回类型blob
	request.onload = function() {
		if (this.status === 200) {
			var blob = request.response;
			var URL = window.URL || window.webkitURL;
			try{
                //正常文件下载
				var name = request.getResponseHeader("Content-disposition");
				var filename = decodeURI(name.substring(21, name.length-1));
				var type=request.getResponseHeader("Content-Type");
				var blobUrl= URL.createObjectURL(blob);
				var a = document.createElement('a');
				a.download = filename;
				a.href = blobUrl;//e.target.result;
				a.click();
				$(a).remove();
			}catch(e){
				var reader = new FileReader();
	            reader.readAsText(blob); // 转换为base64
	            reader.onload = function (e) {
	            	$.messager.alert('提示',e.target.result.split("{")[0].trim(),'info');
	            }
//				$('#myErrorDiv').window('close');  
			}
		}
	}
	request.send();
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!