一、list頁面的js,點擊list列表下面的下載按鈕調用js
function downloadDoc(filePath,fileName){
var path = filePath+fileName;
var contextLength = "<%=request.getContextPath()%>";
var sp = path.substring(contextLength.length,path.length);
document.getElementById("path").value = sp;
document.getElementById("fileName").value = fileName;
//down_frame.location.href = path;decodeURI(path);encodeURIComponent
var sForm1 = document.form1;
sForm1.action = "<%=request.getContextPath()%>/com/icss/mdm/usermanual/servlet/StandardDocDownServlet";
sForm1.submit();
}
下面是 一個form表單
通過的代碼如下:
package com.icss.mdm.usermanual.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.icss.mdm.base.servlet.BaseServlet;
import com.icss.pangu.logging.Log;
import com.icss.pangu.logging.LogFactory;
public class StandardDocDownServlet extends BaseServlet {
private static Log log = LogFactory.getLog(StandardDocDownServlet.class);
public void performTask(HttpServletRequest request, HttpServletResponse response) throws Exception {
String path = getParameter(request, "path", true, true, false, "");
String fileName = getParameter(request, "fileName", true, true, false, "");
request.setAttribute("path", path);
request.setAttribute("fileName", fileName);
if(!"".equals(path) && !"".equals(fileName)){//去函數說明文檔頁面
getServletContext().getRequestDispatcher("/mdm/jsp/usermanual/DownFile.jsp").forward(request,response);
}
}
}
下面是下載的頁面:
<%@ page contentType="text/html;charset=GBK"%>
<%@ page import="java.net.URLEncoder"%>
下載標準文檔
<script language="javascript">
</script>
<%
//去除緩存
/**response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
String contextPath = request.getContextPath();**/
//String path = request.getParameter("path");
//String fileName = request.getParameter("fileName");
String path = (String)request.getAttribute("path");//即將下載的文件的相對路徑
String fileName = (String)request.getAttribute("fileName");//下載文件時顯示的文件保存名稱
response.setContentType("application/x-download");//設置為下載application/x-download
String filedownload = path;//即將下載的文件的相對路徑
String filedisplay = fileName;//下載文件時顯示的文件保存名稱
String filenamedisplay = URLEncoder.encode(filedisplay,"utf-8");
response.addHeader("Content-Disposition","attachment;filename=" + filenamedisplay);
try{
RequestDispatcher dis = application.getRequestDispatcher(filedownload);
if(dis!= null) {
dis.forward(request,response);
}
response.flushBuffer();
} catch(Exception e) {
e.printStackTrace();
} finally{
}
%>
二、采用文件流輸出的方式下載
<%@ page language="java" contentType="application/x-msdownload" pageEncoding="gb2312"%>
<%
//關于文件下載時采用文件流輸出的方式處理:
//加上response.reset(),并且所有的%>后面不要換行,包括最后一個;
response.reset();//可以加也可以不加
response.setContentType("application/x-download");
//application.getRealPath("/main/mvplayer/CapSetup.msi");獲取的物理路徑
String filedownload = "想辦法找到要提供下載的文件的物理路徑+文件名";
String filedisplay = "給用戶提供的下載文件名";
String filedisplay = URLEncoder.encode(filedisplay,"UTF-8");
response.addHeader("Content-Disposition","attachment;filename=" + filedisplay);
try {
java.io.OutputStream outp = response.getOutputStream();
java.io.FileInputStream in = new FileInputStream(filenamedownload);
byte[] b = new byte[1024];
int i = 0;
while((i = in.read(b)) > 0) {
outp.write(b, 0, i);
}
outp.flush();
//要加以下兩句話,否則會報錯
//java.lang.IllegalStateException: getOutputStream() has already been called for //this response
out.clear();
out = pageContext.pushBody();
} catch(Exception e) {
System.out.println("Error!");
e.printStackTrace();
} finally {
if(in != null)
{
in.close();
in = null;
}
if(outp != null) {
outp.close();
outp = null;
}
}
%>
備注:如何出現java.io.: 這個錯誤 則 把out.clear();out = .();這兩個注釋掉就可以解決了。
對于第二種方法,我認為應該是比較常用的。不過有幾個地方是值得我們注意的:
一、采用第二種方法的主要優點是實際文件的存放路徑對客戶端來說是透明的。
這個文件可以存在于任何你的服務器能夠取得到的地方,而客戶端不一定能直接得到。例如文件來自于數據庫或者內部網絡的一個FTP服務器。還句話說,這種方式可以實現隱藏實際文件的URL地址。
二、為了防止客戶端瀏覽器直接打開目標文件(例如在裝了MS 套件的中的IE瀏覽器可能就會直接在IE瀏覽器中打開你想下載的doc或者xls文件),你必須在響應頭里加入強制下載的MIME類型:
.("/force-");//設置為下載/force-
這樣,就可以保證在用戶點擊下載鏈接的時候瀏覽器一定會彈出提示窗口來詢問你是下載還是直接打開并允許你選擇要打開的應用程序,除非你設置了瀏覽器的一些默認行為。
或者,你想讓客戶端自行處理各種不同的文件類型,你可以在服務器的配置文件中配置MIME類型映射,通過簡單的判斷文件后綴名來處理。例如,在中設置MIME響應類型:
如果文件在客戶端中的響應程序類型和期望不一致,修改$\conf\web.xml文件中的如下部分 :
zip
/zip
mht
/
……
三、在響應頭中盡量不要設置瀏覽器緩存期限。
有時候用戶在點擊了下載鏈接后,在彈出窗口中,用戶想直接點擊“打開”,而不想保存到指定路徑。這時候如果我們在響應頭中限制了不允許使用瀏覽器緩存(即總是刷新),在IE瀏覽器中我們將無法直接打開該文件。因為限制了不允許使用緩存,瀏覽器無法將文件保存到臨時文件夾(即緩存)。
也就是說,在響應頭中不要進行如下的設置(已注釋):
//.("","NO-cache");
//.("Cache-","no-cache");
//.("",0);
四、文件名為中文或其他字符時的處理。
有時候提供下載的文件名中包含中文字符或者其他字符,會導致瀏覽器無法正確的采用默認的文件名保存文件。我們應該記住在響應頭中包含字段并采用-1編碼(推薦)或者采用UTF-8編碼:
.("-","; ="+new (.("UTF-8"),"-1")); //采用-1編碼
.("-","; ="+.(, "UTF-8")); //采用UTF-8編碼
但是,這種方式在不同的瀏覽器中表現也有所不同。例如在IE和中,采用-1編碼可以正確顯示文件名jsp 下載文件到本地,而在Opera中不管采用那種編碼,默認保存的文件名都無法做到正確顯示。
所以最好的方法其實就是盡量在文件名中使用ascii編碼。
五、由于采用流的方式進行輸入輸出,我們必須保證在使用完畢后關閉流的資源。
一般我們把關閉流的操作放在塊中jsp 下載文件到本地,以保證在程序段結束前一定會關閉流的資源:
is = null;
sos = null;
try {
is = ...; //通過某種方式讀進數據到輸入流
sos = .(); //打開輸入流
byte[] buff = new byte[2048];
int ;
while(-1 != ( = bis.read(buff, 0, buff.))) {
sos.write(buff,0,);
sos.flush();
}
} catch( ex) {
//TODO with
} catch( ex) {
//TODO with
} {
if(is != null) {
is.close(); //關閉輸入流
}
if(sos != null) {
sos.close(); //關閉輸入流
}
}