1. 目的と仕様
- Java Webアプリケーション(Servlet, JSP)において,JSP内のformに入力された情報(e.g. ユーザネーム, パスワード, 画像)をサーバ(Servlet)にHTTPリクエストで送信する
- form送信前に入力内容を確認し,不備があれば送信しない.そのため動的な処理が必要
- Content-Type : multipart/form-data の場合Servletでリクエストパラメータが取得できないため,フィールドとファイルを同時に取得する方法が必要

2. 方法
- JavaScript
- FormDataオブジェクトでformデータを動的に処理
- Servlet
- Apache Commons FileUploadを用いて受け取ったformデータをフィールドとファイルに分けて処理
3. 環境と準備
- Apache Tomcat 9.0
- commons-fileuploard-1.3.3.jar
- http://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi の commons-fileupload-1.3.3-bin.zip をダウンロードし,解凍して commons-fileuploard-1.3.3.jar を WebContent/WEB-INF/lib に置く
- 過去に脆弱性が報告されているため最新の1.3.3を使用
- commons-io-2.6.jar
- http://commons.apache.org/proper/commons-io/download_io.cgi の commons-io-2.6-bin.zip をダウンロードし,解凍して commons-io-2.6.jar を WebContent/WEB-INF/libに置く
4. 実装
sample.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sample</title>
</head>
<body>
<form id="form">
Username : <input type="text" id="username" name="username"><br>
Password : <input type="password" id="password" name="password"><br>
Image : <input type="file" id="image" name="image" accept="image/*"><br>
<input type="submit" value="send">
</form>
</body>
<script type="text/javascript" src="sample.js"></script>
</html>
sample.js
// formオブジェクトの作成
var form = document.getElementById("form");
// submitイベントが起きたときの処理
form.addEventListener("submit", function(event) {
// formのデフォルト機能を消し,JavaScriptで管理
event.preventDefault();
check();
});
function check() {
// formのvalueを取ってくる
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var image = document.getElementById("image").value;
// 入力されている場合送信
if (username != "" && password != "" && image != "") {
sendData();
} else {
alert("Please input all item.");
}
}
function sendData() {
// FormDataオブジェクトの作成
var formData = new FormData(form);
// XMLHttpRequestでHTTPリクエストを送る
var req = new XMLHttpRequest();
// 送受信が完了した場合の処理
req.addEventListener("load", function(event) {
if (req.responseText == "done") {
// 処理が成功した場合の処理
alert("Succeeded.");
} else {
alert("Failed to send.");
}
});
// 送受信が失敗した場合の処理
req.addEventListener("error", function(event) {
alert("Error");
});
// HTTPリクエストの設定
req.open("POST", "/sample/SampleServlet"); // /application名/Servlet名
// リクエストを送信
req.send(formData);
}
SampleServlet.java
package controller;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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;
@WebServlet("/SampleServlet")
public class SampleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public SampleServlet() {
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
// レスポンステキスト
String responseText = "done";
// DiskFileItemFactoryからServletFileUploadを作成
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(factory);
try {
// リクエストのformデータをリストに格納
List list = sfu.parseRequest(request);
for (Object o : list) {
// formデータの1つ1つをFileItemとして扱う
FileItem item = (FileItem) o;
// FileItemがフィールドかファイルかで分岐
if (item.isFormField()) {
// フィールドの場合,フィールドネームとvalueを取得
// (form内の<input name="フィールドネーム" value="入力内容")
String fieldName = item.getFieldName();
String value = item.getString();
if (fieldName.equals("username")) {
// ユーザネームの処理
System.out.println("username : " + value);
} else if (fieldName.equals("password")){
// パスワードの処理
System.out.println("password : " + value);
}
} else {
File file = new File(item.getName());
try {
String dirPath = "イメージファイルの保存先";
String filePath = dirPath + File.separator + file.getName();
// イメージファイルを保存
item.write(new File(filePath));
} catch (IOException e) {
e.printStackTrace();
responseText = "error";
} catch (Exception e) {
e.printStackTrace();
responseText = "error";
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
responseText = "error";
}
// レスポンスの送信
response.getWriter().print(responseText);
}
}
6. 結果
5. 参考
JavaScript
- XMLHttpRequest : https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
- FormDataオブジェクト : https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects
Servlet