今日は、@MultipartConfig注釈とjavax.servlet.http.Part
を使用したServlet 3ファイルアップロードの例を見てみましょう。以前、Servletファイルのアップロードについての記事を書きましたが、そこではApache FileUpload APIを使用しましたが、ここではServlet 3ファイルのアップロード機能を使用します。
Servlet 3ファイルのアップロード
ファイルのアップロードはWebアプリケーションでよくあるタスクなので、Servlet仕様3.0では、サーバーにファイルをアップロードするための追加のサポートが提供されています。これにより、このためのサードパーティのAPIに依存する必要がありません。このチュートリアルでは、Servlet 3.0 APIを使用してファイルをサーバーにアップロードする方法を見ていきます。
MultipartConfig
ファイルアップロードハンドラーサーブレットには、MultipartConfig注釈を付けて、サーバーへのファイルのアップロードに使用されるmultipart/form-dataリクエストを処理する必要があります。MultipartConfig注釈には、次の属性があります:
- fileSizeThreshold: ファイルがディスクに書き込まれるサイズの閾値を指定できます。サイズの値はバイト単位で指定され、1024*1024*10は10MBです。
- <location: ファイルがデフォルトで保存されるディレクトリです。デフォルト値は””です。
- maxFileSize: ファイルのアップロードに許可される最大サイズです。値はバイトで提供されます。デフォルト値は-1Lで、無制限を意味します。
- maxRequestSize: multipart/form-dataリクエストに許可される最大サイズです。デフォルト値は-1Lで、無制限を意味します。
注釈については、Java注釈チュートリアルを参照してください。
Part Interface
Part interfaceは、multipart/form-data POSTリクエスト内で受信された部分またはフォーム項目を表します。いくつかの重要なメソッドにはgetInputStream()
、write(String fileName)
があり、これらを使用してファイルの読み取りと書き込みができます。
HttpServletRequest Changes
新しい方法がHttpServletRequest
に追加されました。 getParts()
メソッドを使用して、multipart/form-dataリクエスト内のすべての部分を取得できます。 getPart(String partName)
メソッドを使用して特定の部分を取得できます。 servletを使用してファイルをアップロードするために上記のAPIメソッドを使用する単純なプロジェクトを見てみましょう。プロジェクト構造は以下の画像のようになります。
HTMLフォーム
ファイルをアップロードするためのファイルを選択し、サーバーに送信するリクエストを送信できる単純なHTMLページがあります。index.html
<html>
<head></head>
<body>
<form action="FileUploadServlet" method="post" enctype="multipart/form-data">
Select File to Upload:<input type="file" name="fileName">
<br>
<input type="submit" value="Upload">
</form>
</body>
</html>
ファイルアップロードサーブレット
以下はファイルアップロードサーブレットの実装です。FileUploadServlet.java
package com.journaldev.servlet;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/FileUploadServlet")
@MultipartConfig(fileSizeThreshold=1024*1024*10, // 10 MB
maxFileSize=1024*1024*50, // 50 MB
maxRequestSize=1024*1024*100) // 100 MB
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 205242440643911308L;
/**
* Directory where uploaded files will be saved, its relative to
* the web application directory.
*/
private static final String UPLOAD_DIR = "uploads";
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// webアプリケーションの絶対パスを取得
String applicationPath = request.getServletContext().getRealPath("");
// アップロードされたファイルを保存するディレクトリのパスを構築
String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
// 存在しない場合は保存ディレクトリを作成
File fileSaveDir = new File(uploadFilePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdirs();
}
System.out.println("Upload File Directory="+fileSaveDir.getAbsolutePath());
String fileName = null;
// リクエストからすべての部分を取得してサーバー上のファイルに書き込む
for (Part part : request.getParts()) {
fileName = getFileName(part);
part.write(uploadFilePath + File.separator + fileName);
}
request.setAttribute("message", fileName + " File uploaded successfully!");
getServletContext().getRequestDispatcher("/response.jsp").forward(
request, response);
}
/**
* Utility method to get file name from HTTP header content-disposition
*/
private String getFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
System.out.println("content-disposition header= "+contentDisp);
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf("=") + 2, token.length()-1);
}
}
return "";
}
}
@MultipartConfigアノテーションを使用して、アップロードファイルの異なるサイズのパラメーターを指定します。クライアントから送信されたファイル名を取得するには、リクエストヘッダーの「content-disposition」属性を使用する必要があります。ファイルは同じ名前で保存されます。ファイルの保存場所は、ファイルを保存しているWebアプリケーションに相対的ですが、Apache Commons FileUploadの例のように他の場所に設定することもできます。
レスポンスJSP
A simple JSP page that will be sent as response to client once the file is uploaded successfully to server. response.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Upload File Response</title>
</head>
<body>
<%-- Using JSP EL to get message attribute value from request scope --%>
<h2>${requestScope.message}</h2>
</body>
</html>
デプロイメント記述子
Servletファイルのアップロードに関するweb.xmlファイルには何も新しいものがありません。それは単にindex.htmlをウェルカムファイルにするために使用されます。web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ServletFileUploadExample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
アプリケーションを実行すると、次のページが応答として表示されます。
ログには、ファイルが保存されたディレクトリの場所とcontent-dispositionヘッダー情報が表示されます。
Upload File Directory=/Users/pankaj/Documents/workspace/j2ee/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ServletFileUploadExample/uploads
content-disposition header= form-data; name="fileName"; filename="IMG_2046.jpg"
I am running Tomcat through Eclipse, that’s why file location is like this. If you run tomcat through command line and deploy application by exporting as WAR file into webapps directory, you will get different structure but a clear one.
Source:
https://www.digitalocean.com/community/tutorials/servlet-3-file-upload-multipartconfig-part