我們先來看一個最簡單的文件下載的例子:
複製代碼代碼如下:
package com.yyz.response;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//檔案下載
public class ResponseDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String realpath = this.getServletContext().getRealPath("/download/1.gif");
String filename = realpath.substring(realpath.lastIndexOf("//")+1);
response.setHeader("content-disposition", "attachment;filename="+filename);
//伺服器透過這個頭,告訴瀏覽器以下載方式開啟數據
FileInputStream in = new FileInputStream(realpath);
int len = 0;
byte buffer[]=new byte[1024];
OutputStream out = response.getOutputStream();
while((len = in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
//out不用close,response在銷毀的時候伺服器會自動關閉與response相關的串流。
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
此段程式碼的功能是從伺服器端下載圖片1.png。目錄結構用MyEclipse的package explorer顯示如下:
讓我們增加一點難度,我們要下載的檔案是一個中文名字的檔案。由於在http協定中頭檔中的東西只能是ASCII字符,因而透過上述方式(直接將String realpath = this.getServletContext().getRealPath("/download/1.gif");改為String realpath = this .getServletContext().getRealPath("/download/圖片.gif");)直接拿文件,
會出現亂碼問題。附上測試結果:
要解決這個問題,要用到URLEncoder類別的encode方法:
複製代碼代碼如下:
package com.yyz.response;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//中文檔案下載時,中文檔案名稱要經過URL編碼。
public class ResponseDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String realpath = this.getServletContext().getRealPath("/download/圖片.gif");
String filename = realpath.substring(realpath.lastIndexOf("//")+1);
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(filename,"UTF-8"));
//本函數將字串以URL 編碼
FileInputStream in = new FileInputStream(realpath);
int len = 0;
byte buffer[]=new byte[1024];
OutputStream out = response.getOutputStream();
while((len = in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
附上測試結果:
另外這裡有一個小細節要大家注意:
不能用FileReader取代FileInputStream。用FileReader會遺失數據,原因是這樣的:FileReader是字元流,而圖片,媒體檔案等的數據都是以01的方式存儲,用FileReader讀的時候需要查閱一個編碼表,如果未指定一種編碼,則使用相應平台的預設編碼。如在中國的電腦就會去查GB2312。當讀到GB2312碼表中不存在的編碼時,會將該資料編碼成'? ',結束後資料就變成中文和'? '的混合。發到客戶端後顯示時再次查閱碼表,將所有的'?'替換成'?'的編碼,就會遺失資料。向這種細節只需要記住一點:位元組流可以處理任意類型的數據,字元流只能處理字元資料。