1. 程式人生 > >Java Servlet下載檔案(二)

Java Servlet下載檔案(二)




import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicException;
import net.sf.jmimemagic.MagicMatch;
import net.sf.jmimemagic.MagicMatchNotFoundException;
import net.sf.jmimemagic.MagicParseException;

import org.apache.log4j.Logger;

import com.sun.xml.internal.fastinfoset.stax.events.Util;

public class DownloadServlet extends HttpServlet {

private static final long serialVersionUID = 1L;
protected static final Logger logger=Logger.getLogger(DownloadServlet.class);

private String enc = "utf-8";
private String fileRoot = "";
private int bufferSize=2048;


/**
* 初始化 enc,fileRoot
*/
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
String tempStr=config.getInitParameter("enc");
if(!Util.isEmptyString(tempStr)){
enc=tempStr;
}
tempStr=config.getInitParameter("fileRoot");
if(!Util.isEmptyString(tempStr)){
fileRoot=tempStr;
}
tempStr=config.getInitParameter("bufferSize");
if(!Util.isEmptyString(tempStr)){
bufferSize=Integer.parseInt(tempStr);
}

}


public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding(enc);
response.setContentType("text/html;charset="+enc);
//獲取 請求的引數
String filePath=request.getParameter("path");
String fileName=request.getParameter("filename");

if(!Util.isEmptyString(filePath)){
if(Util.isEmptyString(fileRoot)){
fileRoot=request.getSession().getServletContext().getRealPath("/");
}
//獲取檔案的 絕對路徑
String absPath=fileRoot+filePath;
//獲取 檔名
if(Util.isEmptyString(fileName)){
fileName=getFileName(absPath);
}
//安全 校驗不通過
if(!checkFileSafe(filePath)){
StringBuilder sb=new StringBuilder("fileName:").append(fileName).append(" is invalid!");
if(logger.isDebugEnabled()){
logger.debug(sb.toString());
}
response.setContentLength(sb.length());
response.getWriter().print(sb.toString());
return;
}
if(!Util.isEmptyString(absPath)){
try {
if(logger.isDebugEnabled()){
StringBuilder sb=new StringBuilder("fileName:").append(fileName).append(",file absolute path:").append(absPath);
logger.debug(sb.toString());
}
//下載檔案 開始
downloadFile(response,absPath,fileName);
} catch (Exception e) {
StringBuilder sb=new StringBuilder("download file exception,fileName:").append(fileName).append(",file absolute path:").append(absPath);
logger.debug(sb.toString(), e);
sb.delete(0, sb.length());
sb.append("<script type=\"text/javascript\">alert(\"download file err.\");</script>");
response.setCharacterEncoding(enc);
response.setContentLength(sb.length());
response.getWriter().write(sb.toString());
return;
}
}
}else{
StringBuilder sb=new StringBuilder("fileName:").append(fileName).append(",file directory not exists!");
logger.debug(sb.toString());
response.setContentLength(sb.length());
response.getWriter().print(sb.toString());
return;
}
}
/**
* 下載檔案
*
* @param response
* @param absPath 檔案的絕對路徑
* @param fileName 檔案的名字 空時 預設為 絕對路徑的檔名 可以有後綴 或無後綴
* @throws IOException
*/
private void downloadFile(HttpServletResponse response,String absPath,String fileName) throws IOException{
File file=new File(absPath);
//判斷檔案是否存在 和 可讀性
if(!file.exists()|| !file.canRead()){
throw new RuntimeException(" File not exists or can not be read.");
}

String contentType="";
String conentDisposition="attachment;";

if(!Util.isEmptyString(fileName) || !fileName.contains(".")){
contentType=getContentType(file,false);
if(Util.isEmptyString(contentType)){
contentType="application/x-msdownload";
}
}
response.reset();
FileInputStream fis=new FileInputStream(file);
int contentLengh = fis.available();
if(Util.isEmptyString(fileName)){
response.setHeader("Content-Disposition",conentDisposition);
response.setContentType(contentType);
}else if(fileName.contains(".")){ //如果檔案有後綴名 可以不用設定 contentType 瀏覽器會自動判斷檔案型別
response.setHeader("Content-Disposition",conentDisposition+"filename="+convertFileName(fileName));
}
else{ //如果檔名沒有後綴名 需要設定contentType
response.setContentType(contentType);
response.setHeader("Content-Disposition",conentDisposition+"filename="+convertFileName(fileName));
}
if(contentLengh>0){
response.setContentLength(contentLengh);
}

ServletOutputStream sops=response.getOutputStream();
copyStream(fis,sops,true);
fis.close();
sops.close();
fis=null;
sops=null;
file=null;
}
/**
* 複製流 到 前端瀏覽器
* @param source 原始檔輸入流
* @param dest 輸出流
* @param flush
* @return
*/
private final long copyStream(InputStream source,OutputStream dest,boolean flush){
int bytes;
long total=0l;
byte [] buffer=new byte[bufferSize];
try {
while((bytes=source.read(buffer))!=-1){
if(bytes==0){
bytes=source.read();
if(bytes<0)
break;
dest.write(bytes);
if(flush)
dest.flush();
total+=bytes;
}
dest.write(buffer,0,bytes);
if(flush)
dest.flush();
total+=bytes;
}

} catch (IOException e) {
throw new RuntimeException("IOException caught while copying.",e);
}
return total;
}

/**
* 根據傳入的路徑獲取檔名
* @param filePath
* @return
*/
private String getFileName(String filePath){
if(Util.isEmptyString(filePath)){
return "";
}
int index1=filePath.lastIndexOf("/");
int index2=filePath.lastIndexOf("//");
int index=index1 > index2 ?index1:index2;
if(index==-1)
return filePath;
String fileName=filePath.substring(index+1);
return fileName;
}
/**
* 轉換中文檔名
* @param cfilename 中文檔名
* @return
*/
private String convertFileName(String filename){
try {
filename=URLEncoder.encode(filename,enc);
} catch (Exception e) {
e.printStackTrace();
}
return filename;
}

/**
* 獲取檔案的型別
* @param file
* @return
* @throws MagicParseException
* @throws MagicMatchNotFoundException
* @throws MagicException
*/
private String getContentType(File file,boolean extensionHints){
try {
Magic parser = new Magic();
MagicMatch match = parser.getMagicMatch(file, extensionHints);
return match.getMimeType();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

/**
* 檔名的安全檢查,以免被人通過"../../../"的方式獲取其它檔案
* @param filePath
* @return false:不安全 ture:安全
*/
private boolean checkFileSafe(String filePath){
return !filePath.contains("../");
}

}