JQuery Mobile下载文件

2018/12/12 JqueryMobile

JQuery Mobile如何下载文件

前言

JQuery Mobile的请求基本上都是通过Ajax来完成的,但是ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的,文件的下载是以二进制形式进行的也就是流,ajax是不能返回的,虽然可以读取到返回的response,但只是读取而已,是无法执行的。

解决方案,不用ajax:

使用XHR 全称:XMLHttpRequest

废话不多说直接上代码吧:

1. 前端请求

     function downloadAttachments(attachmentId) {
		   var url = 'http://localhost/KRISADMIN/downloadAttachment';
		   var xhr = new XMLHttpRequest();
		   xhr.open('POST', url);// 也可以使用POST方式,根据接口,也可以写get
		  
		  xhr.responseType = "arraybuffer";
		  
		  // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
		   xhr.onload = function () {
	    		   // 请求完成
	    		   if (this.status === 200) {
		    		   // 返回200
		    		   var blob = new Blob([this.response], {type: "application/octet-stream"});
		    		   var reader = new FileReader();
		    		   reader.readAsDataURL(blob);// 转换为base64,可以直接放入a表情href
		    		   
						reader.onload = function (e) {
		    			 //手机浏览器 必须这么保存文件才能正确打开,因为当返回的流很
						//长的时候IE浏览器会报“传递给系统调用的数据区域太小”的错,同时手机浏览器会下载错误的文件
		    		   if(navigator.msSaveBlob){ // IE 10+ 
		    		   	navigator.msSaveBlob(new Blob([blob],{type:'application/octet-stream; charset = utf-8;'}),filename); 
		    		   }else{
		    			  // 转换完成,创建一个a标签用于下载
		    			  var a = document.createElement('a');
		    			   a.download = filename;
		    			   a.href = e.target.result;
		    			   
		    			   $("body").append(a);// 修复firefox中无法触发click
		    			   a.click();
		    			   $(a).remove();  
		    		  }
	    		   }
    		     }
		   };
		   // 发送ajax请求
		   xhr.send(attachmentId)
	}

2. 服务器端

我项目是ssh的,用了rest的插件,接口都是restful接口暴露的。接口如下:

@Action(value="/downloadAttachment")
public void  downloadAttachment() throws IOException{
	ActionContext ctx = ActionContext.getContext();
	String attachmentId = getRequestBody(ctx);
	attachmentId=attachmentId.replaceAll("\"", "");
	WFAttachment wfattachment=workFlowService.findAttachmentByID(Integer.parseInt(attachmentId));
	fileName=wfattachment.getFileName();
	HttpServletRequest request = ServletActionContext.getRequest();
	HttpServletResponse response=ServletActionContext.getResponse();
	 
	String userAgent = request.getHeader("User-Agent");  
       if (null != userAgent && -1 != userAgent.indexOf("Firefox")){ //Firefox  
        	 fileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");     
       }else{     
    	   fileName = URLEncoder.encode(fileName, "UTF-8"); 
    	   fileName = fileName.replace("+", "%20");
       }
       
	   String extension =fileName.substring(fileName.lastIndexOf(".")+1);
	   String path=wfattachment.getSavePath();
	   String strOldNmme = path +"/"+ attachmentId+"."+extension;
	 

	//上面代码都是在我项目中获取文件的过程,文件获取到之后才是重点
	 File f = new File(strOldNmme);
	 
	   
	//导出文件
	String agent = request.getHeader("User-Agent").toUpperCase();
	
	InputStream fis = null;
	OutputStream os = null;
	try {
	    fis = new BufferedInputStream(new FileInputStream(f.getPath()));
	    byte[] buffer;
	    buffer = new byte[fis.available()];
	    fis.read(buffer);
	    response.reset();
	   
		
		//我注释的这段代码是因为在我系统获取fileName时,已经做过这个操作了,就不需要了判断了直接addHeader就行了,你若果在你系统获取filename是没有做此操作,则需要这段代码进行判断添加
		
		/* //由于火狐和其他浏览器显示名称的方式不相同,需要进行不同的编码处理
	    if(agent.indexOf("FIREFOX") != -1){//火狐浏览器
	    	response.addHeader("Content-Disposition", "attachment;filename="+ new String(fileName.getBytes("GB2312"),"ISO-8859-1"));
	    }else{//其他浏览器
	    	response.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8"));
	    }*/
	    response.addHeader("Content-Disposition", "attachment;filename="+ fileName);
	    

		//设置response编码
	    response.setCharacterEncoding("UTF-8");
	    response.addHeader("Content-Length", "" + f.length());
	    //设置输出文件类型(有很多具体可以看setContentType参数,application/octet-stream就是二进制流)  
	    response.setContentType("application/octet-stream");
	    //获取response输出流
	    os = response.getOutputStream();
	    // 输出文件
	    os.write(buffer);
	}catch(Exception e){
	    System.out.println(e.getMessage());
	} finally{
	    //关闭流
	    try {
	        if(fis != null){
	            fis.close();
	        }
	    } catch (IOException e) {
	        System.out.println(e.getMessage());
	    } finally{
	        try {
	            if(os != null){
	                os.flush();
	            }
	        } catch (IOException e) {
	            System.out.println(e.getMessage());
	        } finally{
	            try {
	                if(os != null){
	                    os.close();
	                }
	            } catch (IOException e) {
	                System.out.println(e.getMessage());
	            }
	        }
	    }
	}
	  
	 
}

效果图:

有什么不清楚的,留言一起学习

2018/12/12 18:05:42

Search

    我的微信

    闷骚的程序员

    Table of Contents