文件上傳&下載

文件上傳:html

1.所須要的包:前端

commons-fileupload-1.2.1.jarjava

commons-io-1.4.jarweb

2.瀏覽器端:數據庫

        1>.請求方式必須是 postapache

        2>.須要使用組件<input type="file" name="f">瀏覽器

        3>.表單必須設置encType="multipart/form-data"安全

        4>.上傳文件的input 中,name屬性必需要填寫,否則不會上傳. 服務器

<form action="${pageContext.request.contextPath}/upload2" method="post"	
        enctype="multipart/form-data">
<input type="file" name="f"> 
<input type="submit" value="上傳">
<form/>

3.服務器端:app

    能夠經過request對象,獲取InputStream,能夠將瀏覽器提交的全部請求正文讀取到。

4.核心類的使用:

1.DiskFileItemFactory    用於設置文件上傳時,緩衝區大小以及臨時文件存儲位置.

        1 能夠設置文件上傳緩衝區大小

                factory.setSizeThreshold(1024*1024); //設置爲1m 默認是10k

        2能夠設置臨時文件存儲位置

                File temp=new File(this.getServletContext().getRealPath("/temp"));

                factory.setRepository(temp); //能夠指定臨時文件存儲位置,默認是系統的臨時文件存儲位置

2.ServletFileUpload   它的做用是真正完成解析數據操做上傳類

        1.pareRequest(HttpServletRequest request)

                獲得全部的上傳信息,將每一部分映射成FileItem對象.

        2.isMultipartContent(HttpServletRequest request)

                這個方法返回值是boolean,它是用於判斷當前表單是不是一個上傳的表單,

                簡單說,就判斷它的encType的值是不是 multipart/form-data.

        3.setHeaderEncoding(String encoding)

        用於解決上傳文件名稱中文亂碼問題

        4.能夠設置上傳文件大小,若是超過設置大小.將會拋出異常(默認沒有最大值)

        void setFileSizeMax(long fileSizeMax) 設置單個文件上傳大小 

        void  setSizeMax(long sizeMax) 設置總文件上傳大小 

3.FileItem        它表明的是每個上傳項(其時就是表單中的每個組件)

        1.isFormField()

                這個方法返回的是boolean類型,

                它是判斷當前組件是不是上傳組件 簡單說,就是判斷type="file",

                若是返回true,表明不是上傳組件,返回false,表明是上傳組件

        2.getName()

                獲取非上傳組件的上傳文件的名稱,若是是非上傳組件,返回的是null

        3.getFieldName()

                獲取組件名稱,提交的鍵

        4.getString()

                獲取非上傳組件的value值,

                經過它也能夠獲取上傳的文件內容,可是,使用它獲取不合適。

                若是使用了commons-fileupload進行文件上傳,而上傳表單中包含了

                非上傳組件,獲取其值,不能使用request獲取.

                getString()有一個重載的方法 getString(String encoding)能夠解決亂碼問題

                問題:使用getString()去獲取上傳文件內容不合適,那麼怎樣操做?

        基本操做:

                        經過FileItem.getInputStream();能夠獲取一個輸入流,這個輸入流就能夠讀取出上傳文件內容。

                        InputStream is = item.getInputStream(); // 用於讀取上傳文件內容的輸入流.

                        FileOutputStream fos = new FileOutputStream(

                        "d:/upload/" + filename);


                        int len = -1;

                        byte[] b = new byte[1024 * 10];


                        while ((len = is.read(b)) != -1) {

                        fos.write(b, 0, len);

                        fos.flush();

                        }

                        fos.close();

                        is.close();


                        能夠使用IOUtils工具完成文件copy操做

                        IOUtils.copy(is, fos);

        5.delete方法

          它是用於上傳完成後,刪除臨時文件的

4.注意問題:

        1>關於文件上傳時文件名稱包含中文的亂碼問題?

        調用ServletFileUpload的setHeaderEncoding方法解決

        2>普通表單字段提交時,中文亂碼問題?

        FileItem的 getString方法返回提交的值.經過參數來設置解碼碼錶

                例如: getString("UTF-8");

        3>如何設置上傳文件大小限制?

        調用ServletFileUpload的setSizeMax(總大小)

                setFileSizeMax(每一個大小)方法

        4>上傳文件後,咱們應該把文件保存到什麼位置?

                1.上傳以後,客戶端直接可以訪問到的地方. WEBRoot下

                2.上傳後其餘用戶不能直接訪問

                放到webRoot之外的文件夾. WEB-INF(安全目錄)下或硬盤其餘位置 .例如 d:/xxx

        5>上傳文件時,該使用什麼名字將文件保存?

                文件名稱不能使用用戶命名的名稱.

                用戶命名的名稱咱們須要保存到數據庫中,在下載時使用.

        6>不是用用戶命名的名稱,咱們以什麼名稱保存文件(不能重複)?

        UUID

                登陸用戶名+當前系統毫秒數 (只容許單文件上傳,一個請求只能上傳一個文件)

        7>如何得到用戶命名的文件名?

                getName方法便可得到文件名.

                IE瀏覽器中,會把文件的在客戶端的完整路徑傳過來.須要截取.

                其餘瀏覽器只會文件名稱傳過來.直接使用,無需截取.

        8>爲了防止同一個目錄下方上傳文件數量過多,思考如何解決? 

                 /upload/2016/03/27/xxxx  使用當前日期做爲子文件夾名稱

                當前登陸用戶的用戶名做爲文件夾名稱(不推薦)

實例:

  1. upload.jsp(前端僅貼出相關提交的代碼)

<!-- 
    	1. 表單必須是post提交.
    	2. 修改enctype屬性 . EncodeType 請求正文內容類型. 
    			application/x-www-form-urlencoded (默認值:用於提交文本類型內容).
    			multipart/form-data (多段式提交)
    	3. 文件上傳時,需使用 input type=file 組件
    			注意:  該組件必定要設置name屬性.
    			
     -->
  <body>
	<form action="/upload/AServlet" method="post" enctype="multipart/form-data">
		用戶名:<input type="text" name="username"/><br/>
		<input type="file" name="file1" /><br/>
		<input type="file" name="file2"/>
		<input type="submit" value="提交">
	</form>
  </body>

2.Aservlet.jsp

package cn.test.upload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
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;
import org.apache.commons.io.IOUtils;

public class AServlet extends HttpServlet {

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//1.建立解析器配置工廠
			//DiskFileItemFactory:用於設置文件上傳時,緩衝區的大小以及臨時文件的存儲位置
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//2.根據配置工廠的配置建立解析器類
			//ServletFileUpload:真正完成解析上傳數據的操做類
		ServletFileUpload upload = new ServletFileUpload(factory);
		//3.判斷是否爲多段式方式提交,也就是判斷它的encType的值是不是 multipart/form-data
		if(!upload.isMultipartContent(request)){
			throw new RuntimeException("您的表單提交方式錯誤");
		}
		//設置多段式每一段段頭的編碼表
		upload.setHeaderEncoding("UTF-8");
		//FileItem:表明的就是每個上傳項,其實就是表單中的每個組件
		List<FileItem> list=null;
		//3.調用解析方法,解析request對象
		try {		
			list = upload.parseRequest(request);
		}catch (FileUploadException e) {
			e.printStackTrace();
			throw new RuntimeException("解析request對象失敗!");
		}
		if(list!=null){
			for(FileItem item:list){
				//判斷item爲普通文本提交段
				if(item.isFormField()){
					//得到普通文本提交的鍵
					String key = item.getFieldName();
					//得到普通文本提交的值,使用item.getString()的重載方法,解決中文亂碼問題
					String value = item.getString("UTF-8");
					System.out.println(key+":"+value);
				}
				//處理文件上傳段
				else{
					//獲取上傳的文件名
					//String name = item.getName();
					//System.out.println(name);
					InputStream is = item.getInputStream();
					//將文件保存到upload目錄下(文件名稱不能重複,不能存儲在單一文件夾下)
					//生成uuid文件名稱
					String uuid = UUID.randomUUID().toString();
					//使用日期進行分目錄
					//得到upload目錄所在的絕對路徑
					String dirPath = getServletContext().getRealPath("/upload");
					//根據當前時間,得到時間路徑
					Date date = new Date();
					SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
					String datePath = sdf.format(date);
					//檢查當前時間目錄結構是否存在,若是不存在則建立
					File file = new File(dirPath+datePath);
					if(!file.exists()){
						file.mkdirs();
					}
					//
					InputStream in = item.getInputStream();
					FileOutputStream out = new FileOutputStream(dirPath+datePath+uuid);
					IOUtils.copy(in, out);
					//釋放資源,刪除臨時文件
					out.close();
					in.close();
					item.delete();
				}
			}
		}
	}

}

文件下載

1.文件下載方式

        1> 直接將待下載文件放到webRoot文件夾或子文件夾下.

        2>須要控制資源的下載.在下載前要通過邏輯處理.

  將資源放到用戶不能直接訪問的地方. 例如: WEB-INF  或  d:/upload

2.下載文件名稱中文亂碼問題

        response.setHeader("content-disposition", "attachment;filename="+ filename);

        這段代碼中的filename是指定下載文件時的名稱

        對於IE瀏覽器,它要求必須給一個UTF-8碼

        對於firefox瀏覽器,它要求必須給一個base64編碼

if (agent.contains("MSIE")) {
	// IE瀏覽器
	filename = URLEncoder.encode(filename, "utf-8");
	filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
	// 火狐瀏覽器
	BASE64Encoder base64Encoder = new BASE64Encoder();
	filename = "=?utf-8?B?"
	+ base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
	// 其它瀏覽器
	filename = URLEncoder.encode(filename, "utf-8");					
}

文件下載實例:

1.DownLoadServlet.java

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

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

import org.apache.commons.io.IOUtils;


public class DownloadServlet extends HttpServlet {

	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//1.得到請求的文件名
		String fileName = request.getParameter("name");
		fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8");
		//2.設置content-type頭|content-disposition頭
		response.setContentType(getServletContext().getMimeType(fileName));
		response.setHeader("content-disposition","attachment;filename="+DownloadUtils.encode(fileName, request));
		//3.根據參數指定的文件,找到對應的文件資源流
		InputStream is = getServletContext().getResourceAsStream("/WEB-INF/"+fileName);
		//4.得到向瀏覽器輸出的流
		ServletOutputStream os = response.getOutputStream();
		//5.將兩個流對接
		IOUtils.copy(is, os);
		//6.關閉資源
		is.close();
		os.close();
	}
}

2.DownLoadUtils.java

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


public class DownloadUtils {
	public static String encode(String fileName,HttpServletRequest request){
		//1.得到瀏覽器的類別
		String agent = request.getHeader("User-Agent");
		//2.判斷瀏覽器類型
		if(agent.contains("Firefox")){
			//火狐瀏覽器=>按照base64進行編碼
			BASE64Encoder base64Encoder = new BASE64Encoder();
			try {
				fileName = "=?utf-8?B?" + base64Encoder.encode(fileName.getBytes("utf-8")) + "?=";
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}else{
			//非火狐瀏覽器=>按照urlencoded編碼方式編碼
			 try {
				fileName = URLEncoder.encode(fileName,"UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		//3.返回編碼後的結果
		return fileName;
	}
}

3.download.jsp

<body>
    <a href="/download/DownloadServlet?name=top.csv">下載top.csv文件</a><br/>
    <a href="/download/DownloadServlet?name=走遍中國.JPG">下載圖片_走遍中國</a><br/>
    <a href="/download/DownloadServlet?name=原點.mp3">下載原點.mp3</a>
  </body>
相關文章
相關標籤/搜索