天天看點

java web 檔案上傳下載下傳

檔案上傳下載下傳案例:

首先是此案例工程的目錄結構:

處理上傳: FileUploadServlet.java

1 package fnz.fileUploadTest;
  2 
  3 import java.io.File;
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 import java.io.PrintWriter;
  7 import java.text.SimpleDateFormat;
  8 import java.util.Date;
  9 import java.util.HashMap;
 10 import java.util.List;
 11 import java.util.Map;
 12 
 13 import javax.servlet.ServletException;
 14 import javax.servlet.http.HttpServlet;
 15 import javax.servlet.http.HttpServletRequest;
 16 import javax.servlet.http.HttpServletResponse;
 17 
 18 import org.apache.commons.fileupload.FileItem;
 19 import org.apache.commons.fileupload.FileUploadException;
 20 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 21 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 22 
 23 public class FileUploadServlet extends HttpServlet {
 24 
 25     public void doGet(HttpServletRequest request, HttpServletResponse response)
 26             throws ServletException, IOException {
 27         try {
 28             //建立 FileItem 對象的工廠
 29             DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
 30             //負責處理上傳的檔案資料,并将表單中每個輸入項封裝成一個 FileItem 對象中
 31             ServletFileUpload sfu = new ServletFileUpload(fileItemFactory);
 32             //設定單個檔案最大10M
 33             sfu.setFileSizeMax(10*1024*1024); 
 34             //設定總檔案最大100M
 35             sfu.setSizeMax(100*1024*1024); 
 36             // 設定編碼,相當于:request.setCharacterEncoding("UTF-8");
 37             sfu.setHeaderEncoding("UTF-8");
 38             //判斷上傳表單是否為multipart/form-data類型
 39             if(sfu.isMultipartContent(request)){
 40                 //解析request對象,并把表單中的每一個輸入項包裝成一個fileItem 對象,并傳回一個儲存了所有FileItem的list集合
 41                 List<FileItem> list = sfu.parseRequest(request);
 42                 for (FileItem fileItem : list) {
 43                     //判斷:是否是普通表單字段
 44                     if(fileItem.isFormField()){
 45                         String fieldName = fileItem.getFieldName();//name
 46                         String value = fileItem.getString();//value
 47                         System.out.println(fieldName+" "+value);
 48                     }
 49                     //否則為上傳檔案
 50                     else{
 51                         //String fieldName = fileItem.getFieldName();    // 表單元素名稱 name
 52                         String name = fileItem.getName();            // 檔案名                
 53                         //String content = fileItem.getString();        // 表單元素名稱, 對應的資料 value
 54                         //String type = fileItem.getContentType();    // 檔案類型
 55                         //InputStream in = fileItem.getInputStream(); // 上傳檔案流
 56                         // 擷取項目檔案夾upload對應伺服器上的upload路徑
 57                         String path = getServletContext().getRealPath("/upload");
 58                         
 59                         //用目前時間+檔案名 來命名上傳後的檔案名
 60                         SimpleDateFormat time = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_S");
 61                         String str = time.format(new Date());
 62                         // b. 與檔案名拼接
 63                         name = str +"#"+ name;
 64                         
 65                         //建立一個檔案
 66                         File file = new File(path,name);
 67                         //上傳
 68                         fileItem.write(file);
 69                         //删除系統産生的臨時檔案
 70                         fileItem.delete();  
 71                         System.out.println("OK");
 72                     }
 73                 }
 74             }
 75             
 76         } catch (Exception e) {
 77             throw new RuntimeException(e);
 78         }
 79         
 80         
 81         //将檔案放入request域中
 82         Map<String,String> fileNames = new HashMap<String,String>();
 83         String downFolderPath = getServletContext().getRealPath("/upload");
 84         File file = new File(downFolderPath);
 85         String[] files = file.list();
 86         if(files!=null){
 87             for (String fileItem : files) {
 88                 String[] splitNames = fileItem.split("#");
 89                 fileNames.put(fileItem, splitNames[1]!=null?splitNames[1]:fileItem);
 90             }
 91         }
 92         request.setAttribute("fileNames",fileNames);
 93         request.getRequestDispatcher("/index.jsp").forward(request, response);
 94     }
 95 
 96     public void doPost(HttpServletRequest request, HttpServletResponse response)
 97             throws ServletException, IOException {
 98         this.doGet(request, response);
 99     }
100 
101 }      

處理下載下傳:FileDownLoadServlet.java

1 package fnz.fileUploadTest;
 2 
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 import java.io.OutputStream;
 8 import java.io.PrintWriter;
 9 import java.net.URLEncoder;
10 
11 import javax.servlet.ServletException;
12 import javax.servlet.http.HttpServlet;
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpServletResponse;
15 
16 public class FileDownLoadServlet extends HttpServlet {
17 
18     public void doGet(HttpServletRequest request, HttpServletResponse response)
19             throws ServletException, IOException {
20                 
21                 // 擷取使用者下載下傳的檔案名稱(url位址後追加資料,get)
22                 String fileName = request.getParameter("downFileName");
23                 fileName = new String(fileName.getBytes("ISO8859-1"),"UTF-8");
24                 
25                 // 先擷取上傳目錄路徑
26                 String basePath = getServletContext().getRealPath("/upload");
27                 // 擷取一個檔案流
28                 InputStream in = new FileInputStream(new File(basePath,fileName));
29                 
30                 // 如果檔案名是中文,需要進行url編碼
31                 fileName = URLEncoder.encode(fileName, "UTF-8");
32                 // 設定下載下傳的響應頭
33                 response.setContentType("application/x-msdownload");
34                 response.setHeader("content-disposition", "attachment;fileName=" + fileName);
35                 
36                 // 擷取response位元組流
37                 OutputStream out = response.getOutputStream();
38                 byte[] b = new byte[1024];
39                 int len = -1;
40                 while ((len = in.read(b)) != -1){
41                     out.write(b, 0, len);
42                 }
43                 // 關閉
44                 out.close();
45                 in.close();
46     }
47 
48     public void doPost(HttpServletRequest request, HttpServletResponse response)
49             throws ServletException, IOException {
50         this.doGet(request, response);
51     }
52 
53 }      

前台操作和顯示:index.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
 2 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5   <head>
 6     <title>FileUpload</title>
 7   </head>
 8   
 9   <body>
10     <form action="${pageContext.request.contextPath}/FileUploadServlet" method="post" enctype="multipart/form-data">
11         <input type="file" name="file1"><br/>
12         <input type="submit" value="送出">
13     </form>
14     <hr>
15     已上傳的檔案,點選下載下傳<br/>
16     <c:if test="${not empty requestScope.fileNames }">
17         <c:forEach var="item" items="${requestScope.fileNames}" >
18             <c:url var="url" value="FileDownLoadServlet">
19                 <c:param name="downFileName" value="${item.key}"></c:param>
20             </c:url>
21             <a href="${url }">${item.value }</a><br/>
22         </c:forEach>
23     </c:if>
24   </body>
25 </html>      

檔案上傳和下載下傳注意事項及解釋:

檔案上傳:

<input type="file">标簽用于在web頁面中添加檔案上傳輸入項,設定檔案上傳輸入項時須注意:

1、必須要設定input輸入項的name屬性,否則浏覽器将不會發送上傳檔案的資料。

2、必須把form的enctype屬性值設為multipart/form-data.method

     送出方式設為post方式。設定該值後,浏覽器在上傳檔案時,将把檔案資料附帶在http請求消息體中,并使用MIME協定對上傳的檔案進行描述,以友善接收方對上傳資料進行解析和處理。

使用Commons-fileupload元件實作檔案上傳

需要導入該元件相應的支撐jar包:Commons-fileupload和commons-io。commons-io 不屬于檔案上傳元件的開發jar檔案,但Commons-fileupload 元件從1.1 版本開始,它工作時需要commons-io包的支援。

核心API—DiskFileItemFactory

DiskFileItemFactory 是建立 FileItem 對象的工廠,這個工廠類常用方法:

  public DiskFileItemFactory(int sizeThreshold, java.io.File repository)

  構造函數  

  public void setSizeThreshold(int sizeThreshold)

  設定記憶體緩沖區的大小,預設值為10K。當上傳檔案大于緩沖區大小時, fileupload元件将使用臨時檔案緩存上傳檔案。

  public void setRepository(java.io.File repository)

  指定臨時檔案目錄,預設值為System.getProperty("java.io.tmpdir")

核心API—ServletFileUpload

  ServletFileUpload 負責處理上傳的檔案資料,并将表單中每個輸入項封裝成一個 FileItem 對象中。常用方法有:

  boolean isMultipartContent(HttpServletRequest request)

  判斷上傳表單是否為multipart/form-data類型

  List parseRequest(HttpServletRequest request)

  解析request對象,并把表單中的每一個輸入項包裝成一個fileItem 對象,并傳回一個儲存了所有FileItem的list集合。

  setFileSizeMax(long fileSizeMax)

  設定上傳檔案的最大值

  setSizeMax(long sizeMax)

  設定上傳檔案總量的最大值

  setHeaderEncoding(java.lang.String encoding)

  設定編碼格式

  setProgressListener(ProgressListener pListener)

上傳檔案的處理細節

  中文檔案亂碼問題

    檔案名中文亂碼問題,可調用ServletUpLoader的setHeaderEncoding方法,或者設定request的setCharacterEncoding屬性

  臨時檔案的删除問題

  由于檔案大小超出DiskFileItemFactory.setSizeThreshold方法設定的記憶體緩沖區的大小時,Commons-fileupload元件将使用臨時檔案儲存上傳資料,是以在程式結束時,務必調用FileItem.delete方法删除臨時檔案。

Delete方法的調用必須位于流關閉之後,否則會出現檔案占用,而導緻删除失敗的情況。

檔案存放位置

為保證伺服器安全,上傳檔案應儲存在應用程式的WEB-INF目錄下,或者不受WEB伺服器管理的目錄。

為防止多使用者上傳相同檔案名的檔案,而導緻檔案覆寫的情況發生,檔案上傳程式應保證上傳檔案具有唯一檔案名。

為防止單個目錄下檔案過多,影響檔案讀寫速度,處理上傳檔案的程式應根據可能的檔案上傳總量,選擇合适的目錄結構生成算法,将上傳檔案分散存儲。

ProgressListener顯示上傳進度

ProgressListener progressListener = new ProgressListener() {

    public void update(long pBytesRead, long pContentLength, int pItems) {

    System.out.println("到現在為止,  " + pBytesRead + " 位元組已上傳,總大小為 "

              + pContentLength);

    }

};

upload.setProgressListener(progressListener);

以KB為機關顯示上傳進度

long temp = -1;   //temp注意設定為類變量

long ctemp = pBytesRead /1024;

if (mBytes == ctemp)  

    return;

temp = mBytes;

檔案下載下傳

Web應用中實作檔案下載下傳的兩種方式

超連結直接指向下載下傳資源

程式實作下載下傳需設定兩個響應頭:

設定Content-Type 的值為:application/x-msdownload。Web 伺服器需要告訴浏覽器其所輸出的内容的類型不是普通的文本檔案或 HTML 檔案,而是一個要儲存到本地的下載下傳檔案。

Web 伺服器希望浏覽器不直接處理相應的實體内容,而是由使用者選擇将相應的實體内容儲存到一個檔案中,這需要設定 Content-Disposition 報頭。該報頭指定了接收程式處理資料内容的方式,在 HTTP 應用中隻有 attachment 是标準方式,attachment 表示要求使用者幹預。在 attachment 後面還可以指定 filename 參數,該參數是伺服器建議浏覽器将實體内容儲存到檔案中的檔案名稱。在設定 Content-Dispostion 之前一定要指定 Content-Type

因為要下載下傳的檔案可以是各種類型的檔案,是以要将檔案傳送給用戶端,其相應内容應該被當做二進制來處理,是以應該調用response.getOutputStream()方法傳回 ServeltOutputStream 對象來向用戶端寫入檔案内容。

byte[] b = new byte[1024];

                int len = -1;

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

                    out.write(b, 0, len);

                }