1. 程式人生 > >java web 一行程式碼實現檔案上傳下載

java web 一行程式碼實現檔案上傳下載

       每當要實現檔案上傳下載的功能時,都要複製貼上拼湊程式碼。如果用了不同的框架,程式碼還不一樣,配置啥的一堆,甚是繁瑣,不喜歡。科學家們喜歡把紛繁複雜的自然現象總結為一個個簡潔的公式,我們也來試試,把上傳下載整成一行程式碼~

       花了一天時間,整了個通用的工具類FileUtils,這個類裡實際只包含兩個靜態方法,一個上傳upload(),一個下載download()。只依賴apache的commons-fileupload.jar和commons-io.jar,不依賴struts和spring mvc等框架。乾淨簡潔通用。上傳下載檔案只需一行程式碼即可搞定。現將程式碼貼上來,與大家共享,誰有好的想法,歡迎提議。

工具類:FileUtils.java

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

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

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class FileUtils {

	private FileUtils() {

	}

	public static void download(HttpServletRequest request,
			HttpServletResponse response, String relativeFilePath) {

		try {
			request.setCharacterEncoding("UTF-8");
			response.setCharacterEncoding("UTF-8");
			
			String fileName = request.getSession().getServletContext()
					.getRealPath("/")
					+ relativeFilePath;
			fileName = fileName.replace("\\", "/");//統一分隔符格式
			File file = new File(fileName);
			//如果檔案不存在
			if (file == null || !file.exists()) {
				String msg = "file not exists!";
				System.out.println(msg);
				PrintWriter out = response.getWriter();
				out.write(msg);
				out.flush();
				out.close();
				return;
			}

			String fileType = request.getSession().getServletContext()
					.getMimeType(fileName);
			if (fileType == null) {
				fileType = "application/octet-stream";
			}
			response.setContentType(fileType);
			System.out.println("檔案型別是:" + fileType);
			String simpleName = fileName.substring(fileName.lastIndexOf("/")+1);
			String newFileName = new String(simpleName.getBytes(), "ISO8859-1");
			response.setHeader("Content-disposition", "attachment;filename="+newFileName);

			BufferedInputStream bis = new BufferedInputStream(
					new FileInputStream(file));
			BufferedOutputStream bos = new BufferedOutputStream(
					response.getOutputStream());

			byte[] buffer = new byte[1024];
			int length = 0;

			while ((length = bis.read(buffer)) != -1) {
				bos.write(buffer, 0, length);
			}

			if (bis != null)
				bis.close();
			if (bos != null)
				bos.close();

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 檔案上傳
	 * 
	 * @param request HttpServletRequest
	 * @param relativeUploadPath 上傳檔案儲存的相對路徑,例如"upload/",注意,末尾的"/"不要丟了
	 * @param maxSize 上傳的最大檔案尺寸,單位位元組
	 * @param thresholdSize 最大快取,單位位元組
	 * @param fileTypes 檔案型別,會根據上傳檔案的字尾名判斷。<br>
	 * 比如支援上傳jpg,jpeg,gif,png圖片,那麼此處寫成".jpg .jpeg .gif .png",<br>
	 * 也可以寫成".jpg/.jpeg/.gif/.png",型別之間的分隔符是什麼都可以,甚至可以不要,<br>
	 * 直接寫成".jpg.jpeg.gif.png",但是型別前邊的"."不能丟
	 * @return
	 */
	public static List<String> upload(HttpServletRequest request, String relativeUploadPath, int maxSize, int thresholdSize, String fileTypes) {
		// 設定字元編碼
		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}

		String tempPath = relativeUploadPath + "temp"; // 臨時檔案目錄
		String serverPath = request.getSession().getServletContext().getRealPath("/").replace("\\", "/");
		fileTypes = fileTypes.toLowerCase(); // 將字尾全轉換為小寫

		//如果上傳檔案目錄和臨時目錄不存在則自動建立
		if (!new File(serverPath + relativeUploadPath).isDirectory()) {
			new File(serverPath + relativeUploadPath).mkdirs();
		}
		if (!new File(serverPath + tempPath).isDirectory()) {
			new File(serverPath + tempPath).mkdirs();
		}

		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setSizeThreshold(thresholdSize); // 最大快取
		factory.setRepository(new File(serverPath + tempPath));// 臨時檔案目錄

		ServletFileUpload upload = new ServletFileUpload(factory);

		upload.setSizeMax(maxSize);// 檔案最大上限

		List<String> filePaths = new ArrayList<String>();

		List<FileItem> items;
		try {
			items = upload.parseRequest(request);
			// 獲取所有檔案列表
			for (FileItem item : items) {
				
				// 獲得檔名,檔名包括路徑
				if (!item.isFormField()) { // 如果是檔案
					// 檔名
					String fileName = item.getName().replace("\\", "/");
					//檔案字尾名
					String suffix = null;
					if (fileName.lastIndexOf(".") > -1) {
						suffix = fileName.substring(fileName.lastIndexOf("."));
					} else { //如果檔案沒有後綴名,不處理,直接跳過本次迴圈
						continue;
					}
					
					// 不包含路徑的檔名
					String SimpleFileName = fileName;
					if (fileName.indexOf("/") > -1) {
						SimpleFileName = fileName.substring(fileName
								.lastIndexOf("/") + 1);
					}

					// 如果檔案型別字串中包含該字尾名,儲存該檔案
					if (fileTypes.indexOf(suffix.toLowerCase()) > -1) {
						String uuid = UUID.randomUUID().toString();
						SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
						String absoluteFilePath = serverPath
								+ relativeUploadPath + sf.format(new Date())
								+ " " + uuid + " " + SimpleFileName;
						item.write(new File(absoluteFilePath));
						filePaths.add(absoluteFilePath);
					} 
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return filePaths;
	}

	/**
	 * 檔案上傳
	 * 
	 * @param request HttpServletRequest
	 * @param relativeUploadPath 上傳檔案儲存的相對路徑,例如"upload/",注意,末尾的"/"不要丟了
	 * @param maxSize 上傳的最大檔案尺寸,單位位元組
	 * @param fileTypes 檔案型別,會根據上傳檔案的字尾名判斷。<br>
	 * 比如支援上傳jpg,jpeg,gif,png圖片,那麼此處寫成".jpg .jpeg .gif .png",<br>
	 * 也可以寫成".jpg/.jpeg/.gif/.png",型別之間的分隔符是什麼都可以,甚至可以不要,<br>
	 * 直接寫成".jpg.jpeg.gif.png",但是型別前邊的"."不能丟
	 * @return
	 */
	public static List<String> upload(HttpServletRequest request, String relativeUploadPath, int maxSize, String fileTypes) {
		return upload(request, relativeUploadPath, maxSize, 5*1024, fileTypes);
	}
	
	/**
	 * 檔案上傳,不限大小
	 * 
	 * @param request HttpServletRequest
	 * @param relativeUploadPath 上傳檔案儲存的相對路徑,例如"upload/",注意,末尾的"/"不要丟了
	 * @param fileTypes 檔案型別,會根據上傳檔案的字尾名判斷。<br>
	 * 比如支援上傳jpg,jpeg,gif,png圖片,那麼此處寫成".jpg .jpeg .gif .png",<br>
	 * 也可以寫成".jpg/.jpeg/.gif/.png",型別之間的分隔符是什麼都可以,甚至可以不要,<br>
	 * 直接寫成".jpg.jpeg.gif.png",但是型別前邊的"."不能丟
	 * @return
	 */
	public static List<String> upload(HttpServletRequest request, String relativeUploadPath, String fileTypes) {
		return upload(request, relativeUploadPath, -1, 5*1024, fileTypes);
	}
}
上傳檔案的方法又寫了兩個過載,用法一看便知,不再解釋。

使用示例:FileUtilsTest.java

import java.io.IOException;
import java.util.List;

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

import common.utils.FileUtils;

public class FileUtilsTest extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//下載檔案
		FileUtils.download(request, response, "files/學生資訊.xls");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//上傳檔案
		List<String> filePaths = FileUtils.upload(request, "upload/",".xls .xlsx");
		System.out.println(filePaths);
	}
}


不管是用struts還是spring mvc還是原生的servlet,拿到request,response都是輕而易舉吧,然後上傳下載就只需要上邊的一行程式碼了^_^

測試一下:

看看後臺列印結果:

上傳成功,再來測測下載:

也沒問題。

以後再需要上傳下載功能的時候,只需要匯入兩個jar包,把FileUtils類複製過去,然後FileUtils.download(),FileUtils.upload()就可以啦^_^

專案下載地址:http://download.csdn.net/detail/u013314786/9252777

考慮到專案版本問題,壓縮包中只包含了src和WebRoot兩個資料夾,要執行專案,只需在eclipse或者myeclipse中新建一個名為FileUtils的專案,然後把src裡的檔案複製到專案的src資料夾下,WebRoot裡的檔案複製到專案的WebRoot(myeclipse預設)或者WebContent(eclipse預設)資料夾下就可以執行啦。