JSP/Servletでファイル(画像)をアップロード

JSP&Servlet

Webサービスを作成する際、画像は必須と言えるだろう。今回はフォームから画像をアップロードしてそれを保存する方法を学習する。

準備

今回はエクリプスで行う。新規動的Webプロジェクトを作成し名前をfileuploadとして作成する。その際、サーブレットのバージョンは3.1以上を設定する。

フォルダ構成図

以下が今回のフォルダ構成図だ。迷子になったときはすぐに参照してほしい。

作成

uploadフォルダ作成

まずはファイルがアップロードされるフォルダを作成しよう。新規フォルダからWebContentの直下にuploadフォルダを作成する。すぐにアップロードされた画像を表示したい場合などはWebContentの直下にフォルダを作ってそこに画像をアップロードするのが手っ取り早い。WEB-INFの中に入れないのがポイントだ。

view

まずはフォームの方から作成しよう。WEB-INFの中にviewフォルダを作成し以下のおうにform.jspを作成する。

○form.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>アップロードテスト</title>
</head>
<body>
<form action="/fileupload/Main" method="post" enctype="multipart/form-data">
名前:<input type="text" name="name"><br>
好きな言葉:<input type="text" name="word"><br>
好きな写真:<input type="file" name="pict"><br>
<button type="submit">送信</button>
</form>
</body>
</html>

ファイルアップロードフォーム作成時のポイント

  1. 送信方法はポスト
  2. enctype=”multipart/form-data”を付与
  3. inputのタイプはfile。ネーム属性を付与する

controller

新規サーブレットからMain.javaを作成する。
○controller.Main.java

package controller;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

import javax.servlet.RequestDispatcher;
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("/Main")
@MultipartConfig
public class Main extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher rd=request.getRequestDispatcher("/WEB-INF/view/form.jsp");
		rd.forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		String name=request.getParameter("name");
		String word=request.getParameter("word");
		//name属性がpictのファイルをPartオブジェクトとして取得
		Part part=request.getPart("pict");
		//ファイル名を取得
		//String filename=part.getSubmittedFileName();//ie対応が不要な場合
		String filename=Paths.get(part.getSubmittedFileName()).getFileName().toString();
		//アップロードするフォルダ
		String path=getServletContext().getRealPath("/upload");
		//実際にファイルが保存されるパス確認
		System.out.println(path);
		//書き込み
		part.write(path+File.separator+filename);
		request.setAttribute("name",name);
		request.setAttribute("word", word);
		request.setAttribute("filename", filename);
		RequestDispatcher rd=request.getRequestDispatcher("/WEB-INF/view/result.jsp");
		rd.forward(request, response);
	}
}

ポイントを解説する。
16行目:ファイルアップロードの際にはまずこの
@MultipartConfig
というアノテーションが必要となる。このアノテーションには以下のようなオプションを設定できる。

location: アップロードファイルを一時的に保存するフォルダパス
maxFileSize: アップロードファイルの最大サイズ(バイト)
maxRequestSize: リクエストデータの最大サイズ(バイト)
fileSizeThreshold: 一時保存するファイルサイズの閾値(バイト)

実際にそのサイトを利用する不特定多数のユーザーにファイルアップロードを許すのならばしっかりとmaxFileSizeなどを設定しておいたほうがよい。以下に記述する場合のサンプルを示す。値は適当なので実際にサービスを公開する際はしっかりと値を吟味してもらいたい。

@MultipartConfig(
location="/tmp/files",
maxFileSize=1000000,
maxRequestSize=1000000,
fileSizeThreshold=1000000
)

29行目:
もっとも肝心な部分だ。

Part part=request.getPart(ネーム属性)

まず送信したファイルをPartオブジェクトとして取得する。今回はpictというネーム属性でフォームから飛んでくるのでこれを指定すればよい。(注:ファイルが送信されなかった場合partはnullにならない。もし分岐が必要な際はpart.getSize()==0を利用すると良い)

31行目:

//ファイル名を取得
String filename=part.getSubmittedFileName();
String filename=
Paths.get(part.getSubmittedFileName()).getFileName().toString()

この記述で送信されたファイル名を取得できる。ただし、この書き方ができるのはサーブレット3.1~なので注意が必要だ。(IE対応が必要な場合は下、不要な場合は上を用いる)

33行目:

//アップロードするフォルダ
String path=getServletContext().getRealPath("/upload");

送信されたファイルを格納するフォルダの指定をしている。今回はコンテキストルートの直下にuploadフォルダを作成しその中に格納することとする。ここなら後でimgタグからsrc属性で指定することですぐ表示することができる。

35行目:

//実際にファイルが保存されるパス確認
System.out.println(path);

実際PC内のどこにファイルがアップロードされたかに興味がある人はこれで確認が可能だ。エクリプス内からではこのアップロードされたファイルを直接見ることができないので注意。(ターミナルからならば確認できる)

37行目:

//書き込み
part.write(path+File.separator+filename);

この記述で引数で与えた場所にファイルを保存する。今回はコンテキストルートに
upload/xxxx.jpg
という形で保存する。画像のURLは
http://localhost:8080/fileupload/upload/xxxx.jpg
となる。(ブラウザからアクセス可能)

結果表示

では実際にアップロードされた画像を表示するjspを作成しよう。viewフォルダの中にresult.jspを以下のように作成。

○result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String name=(String)request.getAttribute("name");
	String word=(String)request.getAttribute("word");
	String filename=(String)request.getAttribute("filename");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fileupload</title>
</head>
<body>
<p>名前:<%=name %></p>
<p>好きな言葉:<%=word %></p>
<p>好きな写真:<br><img src="/fileupload/upload/<%=filename %>"></p>
</body>
</html>

今回imgタグでの画像へのパスを(頭に/を入れて)サーバールートからの記述で書いているがコンテキストルートからのパスで以下のように書いても同じことだ。(Webアプリはこのパスをしっかり理解していくことが大切だ)

src="upload/<%=filename %>"

実行

実行してみよう。フォームに名前と好きな言葉を入れ画像をアップロードしてみよう。
以下のように表示されれば成功だ。

完成

今回は画像アップロードの方法を学んだ。Webサービスを作るにあたってこの画像ファイルアップロードはほぼ毎回出てくる大事な処理だ。今回は画像を送ったが他の形式のファイルも同様に送ることができる。しっかりと慣れていこう。

コメント

タイトルとURLをコピーしました