1. 程式人生 > >檔案上傳與下載的功能實現

檔案上傳與下載的功能實現

檔案上傳

檔案上傳原理分析

1、檔案上傳的必要前提:
一、進行檔案上傳時只能使用post方式提交表單
二、表單必須新增一個屬性:enctype=”multipart/form-data”
三、用於上傳檔案的元素必須時

2、enctype屬性
作用:告知伺服器請求正文的MIME型別,作用與content-type一致。
可選值:
a)application/x-www-form-urlencoded(預設)
b)multipart/form-data:
通過字串把普通項和檔案上傳項分開
request.getParameter(String)方法獲取指定的表單欄位字元內容,但檔案上傳表單已經不在是字元內容,而是位元組內容,所以失效。
用傳統取得提交引數的方式得到表單中提交的文字輸入框中的內容
在使用enctype=”multipart/form-data”提交表單後,檔案內容可以被導航才到伺服器,但同時,表單中的其他普通項不能再使用傳統的getPatameter等方式取得其值。

實現檔案上傳功能

1、fileupload
fileupload是由apache的commons元件提供的上傳元件。它最主要的工作就是幫我們解析request.getInputStream()。
匯入commons-fileupload相關jar包
- commons-fileupload.jar,核心包;
- commons-io.jar,依賴包。

//通過請求物件的輸入流可以得到上傳的內容(檔案內容和普通引數)
ServletInputStream is = req.getInputStream();

2、fileupload的核心類的使用
DiskFileItemFactory、ServletFileUpload、FileItem

使用fileupload元件的步驟如下:
1.建立工廠類DiskFileItemFactory物件:
DiskFileItemFactory factory = new DiskFileItemFactory()
2.使用工廠建立解析器物件:
ServletFileUpload fileUpload = new ServletFileUpload(factory)
3.使用解析器來解析request物件:
List list = fileUpload.parseRequest(request)

FileItem物件:
FileItem物件對應一個表單項(表單欄位)。可以是檔案欄位或普通欄位
- boolean isFormField():判斷當前表單欄位是否為普通文字欄位,如果返回false,說明是檔案欄位;
- String getFieldName():獲取欄位名稱,例如:,返回的是username;
- String getString():獲取欄位的內容,如果是檔案欄位,那麼獲取的是檔案內容,當然上傳的檔案必須是文字檔案;
- String getName():獲取檔案欄位的檔名稱;(b.txt)
- String getContentType():獲取上傳的檔案的MIME型別,例如:text/plain。
- int getSize():獲取上傳檔案的大小;
- InputStream getInputStream():獲取上傳檔案對應的輸入流;
- void write(File):把上傳的檔案儲存到指定檔案中。
- delete();

程式碼實現:

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

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;

/**
 * 用於檔案上傳測試的servlet
 * 進行檔案上傳時,只能使用post方式提交表單
 * @author Administrator
 *
 */
public class TestUploadServlet extends HttpServlet{

    /**
     * 測試檔案上傳工具:commons-fileupload的使用方式
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //用於設定檔案上傳時的臨時檔案的目錄等資訊
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //生成核心物件
        ServletFileUpload upload = new ServletFileUpload(factory);
        //使用核心物件對請求輸入流進行解析
        try {
            List<FileItem> parseRequest = upload.parseRequest(req);
            for (FileItem fileItem : parseRequest) {
                if (fileItem.isFormField()) {
                    //普通上傳項(得到名和值)
                    String fieldName = fileItem.getFieldName();
                    String value = fileItem.getString();
                    //測試普通項
                    System.out.println(fieldName+"="+new String(value.getBytes("ISO-8859-1"),"UTF-8"));
                } else {
                    //檔案上傳項(得到名,檔名,檔案內容輸入流,建立檔案輸出流,把上傳檔案寫入伺服器磁碟)
                    //從檔案項物件中得到輸入流
                    InputStream is = fileItem.getInputStream();
                    //建立一個磁碟檔案的輸出流
                    FileOutputStream fis = new FileOutputStream(getServletContext().getRealPath("/demo1/upfile")+"\\"+fileItem.getName());
                    System.out.println(getServletContext().getRealPath("/demo1/upfile"));
                    //流對接
                    byte[] buf= new byte[1024];
                    int len;
                    while ((len = is.read(buf)) > 0) {
                        fis.write(buf, 0, len);
                    }

                    fis.close();
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }

jsp頁面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- 用於測試檔案上傳的表單 -->
    <form action="${pageContext.request.contextPath}/upload.servlet" method="post" enctype="multipart/form-data">
        <input type="text" name="msg" /><br/>
        <input type="file" name="upload" /><br/>
        <input type="submit"  />
    </form>
</body>
</html>

檔案上傳注意事項

a、保證伺服器的安全
把儲存上傳檔案的目錄放在使用者直接訪問不到的地方。
b、避免檔案被覆蓋
讓檔名唯一即可
c、避免同一個資料夾中的檔案過多
方法一:按照日期進行打散儲存目錄
方法二:用檔名的hashCode計算打散的儲存目錄:二級目錄
d、限制檔案的大小:web方式不適合上傳大的檔案
單個檔案大小:
ServletFileUpload.setFileSizeMax(位元組)
總檔案大小:(多檔案上傳)
ServletFileUpload.setSizeMax(位元組)
e、上傳欄位使用者沒有上傳的問題
通過判斷檔名是否為空即可
f、臨時檔案的問題
DiskFileItemFactory:
作用:產生FileItem物件
內部有一個快取,快取大小預設是10Kb。如果上傳的檔案超過10Kb,用磁碟作為快取。
存放快取檔案的目錄預設是系統的臨時目錄。
如果自己用IO流實現的檔案上傳,要在流關閉後,清理臨時檔案。
FileItem.delete();

檔案下載

案例:實現一個具有檔案下載功能的網頁,下載圖片

程式碼實現:

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

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

/**
 * 下載圖片
 * @author Administrator
 *
 */
public class TestDownLoad extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //獲取需要下載檔案的名字
        String fileName = req.getParameter("fileName");
        //轉換編碼
        byte[] bytes = fileName.getBytes("ISO-8859-1");
        fileName = new String(bytes,"UTF-8");

        //通知瀏覽器以下載的方式開啟檔案,如果下載框中顯示的文字是中文的話,又要編碼,瀏覽器彈出的下載框來解碼
        resp.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));

        //假設使用者選中“儲存”,/表示web專案
        InputStream is = this.getServletContext().getResourceAsStream("/images/上海地鐵圖.gif");
        OutputStream os = resp.getOutputStream();

        byte[] buf = new byte[1024*4];
        int len = 0;
        while ((len=is.read(buf))!=-1) {
            os.write(buf,0,len);
        }

        is.close();
        os.close();
    }
}

jps頁面

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>圖片下載</title>
</head>
  <body>
    <!-- /表示webapps目錄
         對於GET請求後邊帶中文的情況下,需要進行UTF-8編碼後,再傳遞到伺服器
     -->
    <a href="/javaweb/demo11?fileName=%E4%B8%8A%E6%B5%B7%E5%9C%B0%E9%93%81%E5%9B%BE.gif" style="text-decoration:none;">上海地鐵圖.gif</a>
  </body>
</html>