文件下載

解決springmvc中文件下載功能中使用javax.servlet.ServletOutputStream out = response.getOutputStream();後運行出異常但結果正確的問題

 

問題描述:html

  在springmvc中實現文件下載功能通常都會使用javax.servlet.ServletOutputStream out = response.getOutputStream();封裝下載的工具類,稍後我會分享該工具類。java

當使用了response.getOutputStream()後,因爲在同一個請求中JSP或Servlet中同時調用了Response的getWriter和getOutputStream就會拋此異常,異常部分代碼以下:web

複製代碼
嚴重: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
    at org.apache.catalina.connector.Response.getWriter(Response.java:678)
    at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:213)
    at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:104)
    at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
    at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
    at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:186)
    at org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:126)
    at org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:80)
    at org.apache.jsp.download_jsp._jspService(download_jsp.java:103)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:395)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
複製代碼

網上有的解決辦法都是基於jsp中有java代碼的,可是若是想在springmvc的controller中使用時不免不太對應,通過個人摸索,因爲下載文件大多數狀況況下都是留在原頁面,那麼我試了一下將返回值設爲void,結果巧妙解決了以上問題,特以此記錄。spring

測試的下載工具類以下:;apache

複製代碼
 
   
複製代碼
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DownloadFile {
    /**
     * 下載文件,file 爲文件位置
     */
    public static void downloadFile(String file, HttpServletRequest request,
            HttpServletResponse response) {
        try {
            File tempFile = new File(file.trim());
            String fileName = tempFile.getName();
            InputStream is = new FileInputStream(file);
            response.reset(); // 必要地清除response中的緩存信息
            request.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream; charset=utf-8");
            response.setHeader("Content-disposition", 
                               "attachment;" + UserAgentUtil.encodeFileName(request, fileName));
            //response.setHeader("Content-Length", String.valueOf(fileLength));
            /*response.setHeader("Content-Disposition", "attachment; filename="
                    + java.net.URLEncoder.encode(fileName, "UTF-8"));*/
            javax.servlet.ServletOutputStream out = response.getOutputStream();
            byte[] content = new byte[1024];
            int length = 0;
            while ((length = is.read(content)) != -1) {
                out.write(content, 0, length);
            }
            out.flush();
            out.close();
       is.close(); } catch (Exception e) { e.printStackTrace(); } } }
複製代碼
複製代碼

測試的controller層代碼以下:瀏覽器

複製代碼
@RequestMapping(value = "/download.do")    
    public void downloadDetailPrice(//@RequestParam String id, 
            HttpServletRequest request, HttpServletResponse response) {
        String file = "D:\\a.txt";
        DownloadFile.downloadFile(file,request,response);
            
    } 
複製代碼

 瀏覽器客戶端防亂碼工具類:緩存

複製代碼
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.mail.internet.MimeUtility;
import javax.servlet.http.HttpServletRequest;


/** @author  pangchao E-mail: pangchao620@163.com
 * @date : 2016年2月24日 上午11:27:26 
 * @Description : 文件下載時瀏覽器端防亂碼編碼工具類
 * @version 1.0 
 */
public class UserAgentUtil {

    public static String encodeFileName(HttpServletRequest request, String fileName) {
        String userAgent = request.getHeader("User-Agent");
        String rtn = "";
        try {
            String new_filename = URLEncoder.encode(fileName, "UTF8");
            // 若是沒有UA,則默認使用IE的方式進行編碼,由於畢竟IE仍是佔多數的
            rtn = "filename=\"" + new_filename + "\"";
            if (userAgent != null) {
                userAgent = userAgent.toLowerCase();
                // IE瀏覽器,只能採用URLEncoder編碼
                if (userAgent.indexOf("msie") != -1) {
                    rtn = "filename=\"" + new_filename + "\"";
                }
                // Opera瀏覽器只能採用filename*
                else if (userAgent.indexOf("opera") != -1) {
                    rtn = "filename*=UTF-8''" + new_filename;
                }
                // Safari瀏覽器,只能採用ISO編碼的中文輸出
                else if (userAgent.indexOf("safari") != -1) {
                    rtn = "filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO8859-1") + "\"";
                }
                // Chrome瀏覽器,只能採用MimeUtility編碼或ISO編碼的中文輸出
                else if (userAgent.indexOf("applewebkit") != -1) {
                    new_filename = MimeUtility.encodeText(fileName, "UTF8", "B");
                    rtn = "filename=\"" + new_filename + "\"";
                }
                // FireFox瀏覽器,能夠使用MimeUtility或filename*或ISO編碼的中文輸出
                else if (userAgent.indexOf("mozilla") != -1) {
                    rtn = "filename*=UTF-8''" + new_filename;
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return rtn;
    }
}
相關文章
相關標籤/搜索