mike-neckのブログ

Java or Groovy or Swift or Golang

Servlet3.1のファイルアップロードが思いの外簡単だった件

こんにちわ、みけです。

Servlet3.0のファイルアップロードを触ったことがなかったので、ためしにさわってみました。

作ろうとしたもの

  • ファイルをアップロードできる
  • 送信できるファイルのサイズは1Mまで
  • 送られてきたファイルの名前はyyyy-MM-dd-hh-mm-ss-SSS.拡張子の形で保存

サンプルコード

<input type="file" name="upload-file"/>
@WebServlet(name = "file-upload", urlPatterns = "multipart", asyncSupported = true)
@MultipartConfig(fileSizeThreshold = 1, maxFileSize = 1048576, location = "upload")
public class FileUploadServlet extends HttpServlet {

    private static final ZoneId HERE = ZoneId.of("Asia/Tokyo");

    private static final DateTimeFormatter PATTERN = DateTimeFormatter.ofPattern(
            "uuuu-MM-dd-HH-mm-ss-SSS");

    private static final String FILE = "upload-file";

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        ZonedDateTime now = ZonedDateTime.now(HERE);
        String fileName = now.format(PATTERN);
        Part file = req.getPart(FILE);
        String extension = Optional.of(file.getSubmittedFileName())
                .filter(s -> s.length() > 0)
                .filter(s -> s.contains("."))
                .map(s -> s.substring(s.lastIndexOf(".")))
                .orElse("");
        file.write(fileName + extension);
    }
}

javax.servlet.http.Part#write(String)だけで、ファイルを書き出してくれました。

なお例外ハンドリングしていないので、ファイルサイズオーバーした時とかの動作保証はしません。

あとnullなケースも。


以上

【2014/10/30 15:43追記】 参考にしていたのがServlet 3.0 File Upload 機能だったのですが、その後3.1の時にPart#getSubmittedFileName()というメソッドが追加されていたので、そっちの方が便利だなと思って書き直しました。

【2014/10/30 15:59追記】

  • ファイルサイズが@MultipartConfigmaxFileSizeを超えているか、@MultipartConfigweb.xmlmultipart-configがない場合にHttpServletRequest#getPartをやると、IllegalStateExceptionが返されます。
  • ファイルが送信されていない場合にはHttpServletRequest#getPartをするとPartインスタンスは返ってきます。ただし、Part#getSubimttedFileNameは長さ0の文字列を返します。