比如,downLoadFile.jsp?fileName=d:/file/20150227-0002.ZIP,實現下載。
<%@page contentType = " text/html; charset=GBK" pageEncoding ="GBK" %>
<%@ page import = " java.io.*, java.util.*, java.text.* " %>
<%!
/**
* If returns true, then should return a 304 (HTTP_NOT_MODIFIED)
*/
public static boolean checkFor304( HttpServletRequest req,
File file )
{
//
// We'll do some handling for CONDITIONAL GET (and return a 304)
// If the client has set the following headers, do not try for a 304.
//
// pragma: no-cache
// cache-control: no-cache
//
if ( "no-cache" .equalsIgnoreCase(req.getHeader( "Pragma" ))
|| "no-cache" .equalsIgnoreCase(req.getHeader( "cache-control" )))
{
// Wants specifically a fresh copy
}
else
{
//
// HTTP 1.1 ETags go first
//
String thisTag = Long.toString(file.lastModified());
String eTag = req.getHeader( "If-None-Match" );
if ( eTag != null )
{
if ( eTag.equals(thisTag) )
{
return true ;
}
}
//
// Next, try if-modified-since
//
DateFormat rfcDateFormat = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss z" );
Date lastModified = new Date(file.lastModified());
try
{
long ifModifiedSince = req.getDateHeader( "If-Modified-Since" );
// log.info("ifModifiedSince:"+ifModifiedSince);
if ( ifModifiedSince != - 1 )
{
long lastModifiedTime = lastModified.getTime();
// log.info("lastModifiedTime:" + lastModifiedTime);
if ( lastModifiedTime <= ifModifiedSince )
{
return true ;
}
}
else
{
try
{
String s = req.getHeader( "If-Modified-Since" );
if ( s != null )
{
Date ifModifiedSinceDate = rfcDateFormat.parse(s);
// log.info("ifModifiedSinceDate:" + ifModifiedSinceDate);
if ( lastModified.before(ifModifiedSinceDate) )
{
return true ;
}
}
}
catch (ParseException e)
{
// log.warn(e.getLocalizedMessage(), e);
}
}
}
catch ( IllegalArgumentException e )
{
// Illegal date/time header format.
// We fail quietly, and return false.
// FIXME: Should really move to ETags.
}
}
return false ;
}
%>
<%
// String filePath = "c:/文檔.doc";
// 如果是 WEB APP 下的相對路徑文件, 請使用下列代碼:
String filePath = request.getParameter("fileName");
boolean isInline = false ; // 是否允許直接在瀏覽器內打開(如果瀏覽器能夠預覽此文件內容,
// 那麼文件將被打開, 否則會提示下載)
// 清空緩衝區, 防止頁面中的空行, 空格添加到要下載的文件內容中去
// 如果不清空的話在調用 response.reset() 的時候 Tomcat 會報錯
// java.lang.IllegalStateException: getOutputStream() has already been called for
// this response,
out.clear();
// {{{ BEA Weblogic 必讀
// 修正 Bea Weblogic 出現 "getOutputStream() has already been called for this response"錯誤的問題
// 關於文件下載時採用文件流輸出的方式處理:
// 加上response.reset(),並且所有的%>後面不要換行,包括最後一個;
// 因爲Application Server在處理編譯jsp時對於%>和<%之間的內容一般是原樣輸出,而且默認是PrintWriter,
// 而你卻要進行流輸出:ServletOutputStream,這樣做相當於試圖在Servlet中使用兩種輸出機制,
// 就會發生:getOutputStream() has already been called for this response的錯誤
// 詳細請見《More Java Pitfill》一書的第二部分 Web層Item 33:試圖在Servlet中使用兩種輸出機制 270
// 而且如果有換行,對於文本文件沒有什麼問題,但是對於其它格式,比如AutoCAD、Word、Excel等文件
// 下載下來的文件中就會多出一些換行符0x0d和0x0a,這樣可能導致某些格式的文件無法打開,有些也可以正常打開。
// 同時這種方式也能清空緩衝區, 防止頁面中的空行等輸出到下載內容裏去
response.reset();
// }}}
try {
java.io.File f = new java.io.File(filePath);
if (f.exists() && f.canRead()) {
// 我們要檢查客戶端的緩存中是否已經有了此文件的最新版本, 這時候就告訴
// 客戶端無需重新下載了, 當然如果不想檢查也沒有關係
if ( checkFor304( request, f ) )
{
// 客戶端已經有了最新版本, 返回 304
response.sendError( HttpServletResponse.SC_NOT_MODIFIED );
return ;
}
// 從服務器的配置來讀取文件的 contentType 並設置此contentType, 不推薦設置爲
// application/x-download, 因爲有時候我們的客戶可能會希望在瀏覽器裏直接打開,
// 如 Excel 報表, 而且 application/x-download 也不是一個標準的 mime type,
// 似乎 FireFox 就不認識這種格式的 mime type
String mimetype = null ;
mimetype = application.getMimeType( filePath );
if ( mimetype == null )
{
mimetype = "application/octet-stream;charset=ISO8859-1" ;
}
// IE 的話就只能用 IE 才認識的頭才能下載 HTML 文件, 否則 IE 必定要打開此文件!
String ua = request.getHeader( "User-Agent" ); // 獲取終端類型
if (ua == null ) ua = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0;)" ;
boolean isIE = ua.toLowerCase().indexOf( "msie" ) != - 1 ; // 是否爲 IE
if (isIE && ! isInline) {
mimetype = "application/x-msdownload" ;
}
System.out.println("mimetype="+mimetype);
response.setContentType( mimetype );
// 下面我們將設法讓客戶端保存文件的時候顯示正確的文件名, 具體就是將文件名
// 轉換爲 ISO8859-1 編碼
String downFileName = new String(f.getName().getBytes(), "ISO8859-1" );
String inlineType = isInline ? "inline" : "attachment" ; // 是否內聯附件
System.out.println("inlineType1 ="+inlineType);
// or using this, but this header might not supported by FireFox
// response.setContentType("application/x-download");
response.setHeader ( "Content-Disposition" , inlineType + ";filename=\""+ downFileName + " \"" );
response.setContentLength(( int ) f.length()); // 設置下載內容大小
byte [] buffer = new byte [ 4096 ]; // 緩衝區
BufferedOutputStream output = null ;
BufferedInputStream input = null ;
//
try {
output = new BufferedOutputStream(response.getOutputStream());
input = new BufferedInputStream( new FileInputStream(f));
int n = ( - 1 );
while ((n = input.read(buffer, 0 , 4096 )) > - 1 ) {
output.write(buffer, 0 , n);
}
response.flushBuffer();
}
catch (Exception e) {
} // 用戶可能取消了下載
finally {
if (input != null ) input.close();
if (output != null ) output.close();
}
}
return ;
} catch (Exception ex) {
ex.printStackTrace();
}
// 如果下載失敗了就告訴用戶此文件不存在
response.sendError( 404 );
%>
比如,downLoadFile.jsp?fileName=d:/file/20150227-0002.ZIP,實現下載。