調べてみたら素直に実装できなかったので、メモとして残しておきます。
ファイル+パラメータを送信するアップロード要件はそれなりにある
かんたんに、以下のアップロードフォームがあった場合、サーブレット3.0からはサーブレットからアップロードファイルを取得できます。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>upload</title>
</head>
<body>
<form action="UploadServlet" enctype="multipart/form-data" method="post">
<input type="file" name="target">
<input type="text" name="param">
<input type="submit">
</form>
</body>
</html>
このHTMLに対して、受信するサーブレットはマルチパートを受け取れるよう、以下のようにしておけば、
@WebServlet("/UploadServlet")
@MultipartConfig()
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Collection<Part> parts = request.getParts();
parts.stream().forEach(part -> {
log("name:" + part.getName());
String contentType = part.getContentType();
こういう感じで、名前とファイルのコンテンツタイプが取れますので、コンテンツタイプを見て拒否なんかもできます。
が、同時に送られてきたパラメータ値は、以下の特徴があります。
- コンテンツタイプはnullとなる
- javax.servlet.http.Part に getName()はあるが、getValue() や getParameter() は そもそもない
ではどうするか → getInputStream() は使えるので、これを使って Stringを生み出せば 、パラメータ値は取れます。
Java8時代なので
割と雑な実装ですが、次のようにするとパラメータ値が取得できます。
package sample.upload;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.stream.Collectors;
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;
/**
* Servlet implementation class UploadServlet
*/
@WebServlet("/UploadServlet")
@MultipartConfig()
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Collection<Part> parts = request.getParts();
parts.stream().forEach(part -> {
log("name:" + part.getName());
String contentType = part.getContentType();
log("contentType:" + contentType);
if ( contentType == null) {
try(InputStream inputStream = part.getInputStream()) {
BufferedReader bufReader = new BufferedReader(new InputStreamReader(inputStream));
log( bufReader.lines().collect(Collectors.joining()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
}
}
BufferedReaderに入れてしまって、特に文字コードも気にせず、lines()→collectors.joiningしてしまうあたりが雑ですね(´・ω・`)