2020-03-14
JAVASERVLETHTML

Servlet 檔案處理

Servlet 接收檔案、儲存檔案會牽涉到不少基礎的檔案處理,包括 InputStream、OutputStream、byte...

Servlet File

Servlet 接收檔案、儲存檔案會牽涉到不少基礎的檔案處理,包括 InputStream、OutputStream、byte … 就不要多說了,說多了嚇人而已,直接開始吧!

InputStream、OutputStream

在用 Java 做檔案處理的時候,一定會碰到的就是 InputStream、OutputStream 我們在 OPENHOME InputStream、OutputStream 可以看到非常完整的講解 同時我也覺得他們的水管圖超棒, 真的是我看過對 Java 的 Input / Output 最清晰的解釋了! ( 簡直是 做超好的教學 讓別人沒東西寫呀~ )

這邊就不對 Input / Output 多做解釋了! 我們馬上來看看 Servlet 中接受檔案是怎麽個一回事吧!

Servlet Post 方法處理

上次 Servlet 接收參數 的最後,有偷偷寫了一小段 doPost 的處理,但由於什麼都沒有學過,我們就在這邊從頭來學過吧!

doPost

上傳單個檔案 getPart()

先來個上傳檔案表單

<!DOCTYPE html>
<html>
<body>
  <form
    action="http://localhost:8080/tomcat-hello/file-upload"
    method="POST"
    enctype="multipart/form-data"
  >
    <input type="file" name="file">
    <button type="submit">送出</button>
  </form>
</body>
</html>

Servlet 物件

@MultipartConfig() // 這個是為了要使用 getPart() 方法一定要加的哦!
@WebServlet(
        name = "FileUpload",
        urlPatterns = {"/file-upload"}, // 等等要把這串敲在網頁根目錄之後
        loadOnStartup = 1
)
public class FileUpload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Part filePart = req.getPart("file");
        String filename = filePart.getSubmittedFileName(); // 取得檔名

        InputStream in = filePart.getInputStream(); // 取得 InputStream
        OutputStream out = new FileOutputStream("/your/path/" + filename); // 定義 OutputStram 輸出位置
        byte[] buffer = new byte[1024];
        int length = -1;
        while ((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length); // 檔案寫入
        }
    }
}

getPart() 方法接受一個字串參數,字串就是我們 form 表單的 name 阿記得如果要使用 getPart() 方法,Servlet 一定要有標註 @MultipartConfig 如果對 @MultipartConfig 有興趣的話,我有單獨寫一篇關於註解的整理,請大家多多照料了~

上傳多個檔案 getParts()

其實我們也可以一次上傳多個檔案 再來個上傳表單看看

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <form
    action="http://localhost:8080/tomcat-hello/parts-upload"
    method="POST"
    enctype="multipart/form-data"
  >
    <input type="file" name="file">
    <input type="file" name="file">
    <input type="file" name="file">
    <input type="file" name="file">
    <button type="submit">送出</button>
  </form>
</body>
</html>

Servlet 物件

@MultipartConfig(
        // 當檔案處理中、或檔案大小超過 fileSizeThreshold 定義時的暫存目錄
        // 另外 Part 的 .write() 方法也是預設會把檔案寫進這個目錄
        location = "/your/path",
        fileSizeThreshold = 1024 * 1024 * 20, // 定義檔案暫存門檻
        maxFileSize = 1024 * 1024 * 20, // 允許單個檔案最大大小;當上傳檔案大小超過定義會丟出 exception (IllegalStateException)
        maxRequestSize = 1024 * 1024 * 20 // 允許整個 multipart/form-data 要求最大大小;當上傳檔案大小超過定義會丟出 exception (IllegalStateException)
)
@WebServlet(
        name = "PartsUpload",
        urlPatterns = {"/parts-upload"}, // 等等要把這串敲在網頁根目錄之後
        loadOnStartup = 1
)
public class PartsUpload extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Collection<Part> partCollection = req.getParts(); // 把所有傳入的 Part 都抓出來
        for (Part part : partCollection) {
            String partName = part.getName(); // form 表單的欄位
            if (Objects.equals(partName, "file")) {
                // write() 方法會去看 @MultipartConfig 定義的 location 位置寫檔案
                part.write(part.getSubmittedFileName());
            }
        }
    }
}

這次的 Servlet 物件我多用了很多 @MultipartConfig 的相關屬性,目的是希望讀者們可以多看看。 其實現在 Servlet 單純檔案的上傳,是不需要碰到恐怖的 Input / Output 的, 只要定義了 location 屬性 再呼叫 Part 的 .write() 方法,就會自己寫到 location 定義的資料夾位置底下了!

另外 Parts() 方法會回傳一個 Collection ,Collection裡面包裹的是傳過來的每個 Part 物件,不論是一段字還是檔案,都會囊括在裡面 那這邊的範例,我們直接用 for 迴圈把 Collection 迭代出來, 再透過 getName() 方法確認 form 表單傳過來的 name 是否為 "file" 確認過後直接使用 part 的 write() 方法,進行檔案的寫入動作!


今天就到這邊吧!之後,我們來練習包成一個 zip 吧!