後臺二進制文件 在前臺下載方法總結

總結下實際開發過程當中使用過的文件下載方法:javascript

剛開始接觸$.ajax()時 欣喜若狂,覺得全部的異步交互均可以用它來操做,直到流文件。具體的場景是:html

  • 後臺操做文件 ,以二進制流的形式,返回到前臺(我實際的場景是導出Excel文件)
  • context.Response.BinaryWrite(二進制數組);

首先想到的是經過$.ajax來進行操做,由於和後臺交互的參數不少,它的參數形式能夠用鍵值對對象的形式,很方便,html5

可是怎麼操做都不行,不報錯,可是文件就是不能下載,又想到設置dataType的形式,發現沒文件流的形式,心中java

一萬個…….jquery

廢話少說,總結方法:web

(1)經過a標籤的形式,應該能夠知足大多的需求。ajax

就是經過設置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.locationapp

  • 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();
}
相關文章
相關標籤/搜索