トップ 新規 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

JSPの実際:ファイルのアップロード

Servlet3.0以降の例

  • serlvet.FileUploadServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package 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;

@SuppressWarnings("serial")
@WebServlet(name = "FileUploadServlet", urlPatterns = { "/upload" })
@MultipartConfig(maxFileSize = 100000, maxRequestSize = 100000, fileSizeThreshold = 100000)
public class FileUploadServlet extends HttpServlet {
    final static String REPOSITORY_PATH="/WEB-INF/repository/";
    @Override
    public void init() throws ServletException {
        new File(getServletContext().getRealPath(REPOSITORY_PATH)).mkdirs();
    }
    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        forwardJsp(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Part part = request.getPart("fileupload");
        String fileName = getFileName(part);
        if(fileName!=null) {
            part.write(getServletContext().getRealPath(REPOSITORY_PATH+fileName));
        }
        forwardJsp(request,response);
    }
    private void forwardJsp(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("files", new File(getServletContext().getRealPath(REPOSITORY_PATH)).listFiles());
        request.getRequestDispatcher("/uploader/upload.jsp").forward(request, response);
    }
    private String getFileName(Part part) {
        for (String content : part.getHeader("content-disposition").split(";")) {
            if (content.trim().startsWith("filename")) {
                return content.substring(content.indexOf('=') + 1).trim()
                        .replace("\"", "");
            }
        }
        return null;
    }
}
  • uploader/upload.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ファイルアップロード</title>
</head>
<body>
    <form method="POST" action="${pageContext.request.contextPath}/upload"
        enctype="multipart/form-data">
        <input type="file" name="fileupload"> <br> <input
            type="submit" value="アップロード">
    </form>
    <hr>
    <table>
        <tr>
            <th>ファイル名</th>
        </tr>
        <c:forEach items="${files}" var="f">
            <tr>
                <td>${f.name}</td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>

Commonsのライブラリを使う例

 アップロードの準備(ライブラリの設定)

Jakarta Commonsのライブラリ

Jakarta Commonsの使い方

  • JavaDoc API http://commons.apache.org/fileupload/apidocs/
  • DiskFileItemFactoryクラス
    • ファイルのアップロードがされるさいのメモリのバッファや一時ファイルを管理するクラス。大きなファイルのアップロードがされる場合にはもちろんきちんと設定すべきであるが、そうでない場合でも利用者が大きなファイルを誤ってアップロードすることが想定されるため、きちんと設定した方がよい。
    • setRepository(File repository)メソッド
      • 一時ファイルを指定するメソッド。最終的に保存される場所ではないのに注意する。
  • ServletFileUploadクラス
    • multipart/form-dataなどを抽象化して普通に扱うことができるようにしているクラス。ファイルの最大サイズなどの指定はこのクラスに対して行う。
    • isMultipartContent(Request request)メソッド
      • 引数で指定されたリクエストにmultipartデータが含まれるかを返す。ファイルのアップロードがされるフォームの場合には原則的にmultipart/form-dataであるため、このメソッドを使うことでアップロードされるファイルがあるかを識別することができる。
    • setHeaderEncoding(String encoding)メソッド
      • 引数で指定された文字コードでヘッダのパースを行う。指定されない場合、requestの文字コードが指定される。ページを表示する文字コードと合わせることでファイル名の文字化けが防げる場合が多い。
    • setSizeMax(long sizeMax)メソッド
      • アップロードできるリクエストの最大サイズを指定する。全体の大きさを指定することになる点が、以下のsetFileSizeMax()メソッドとは異なる。
    • setFileSizeMax(long sizeMax)メソッド
      • アップロードできる一ファイルの最大サイズを指定する。
  • FileItemインタフェース
    • isFormField()メソッド
      • falseの場合、アップロードされたデータであることを示す。
    • write(File file)メソッド
      • アップロードされたファイルを引数で指定されたファイルに書き出す。

 アップロード用フォーム

  • アップロードされるファイルはフォームデータとしては大きすぎることもあるため、formタグのenctype属性を"multipart/form-data"に設定し、データを分割して送信することになる。そのため、一般的なリクエストパラメータとは異なり、分割されたデータの統合が必要になる。ここではJakarta CommonsのFileUploadライブラリを用いることで、その部分の面倒な処理をライブラリに任せる形で処理を行う。
  • ファイルアップロードのinputタグはtype属性を"file"に設定することで、アップロードするファイルの参照ボタンも自動的に付与される。
  • formとinputタグの書式
<form 〜 enctype="multipart/form-data">
   <input type="file" 〜 />
</form>

 ファイルアップロードの例1:単なるアップロード

  • アップロードされたファイルの名前を表示し、もしテキストファイルならばその内容を表示する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="java.util.List"%>
<%@page import="java.io.File"%>
<%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>ファイルのアップロード</title>
</head>
<body>
    <form action="${pageContext.request.requestURI}" method="post" enctype="multipart/form-data" >
        アップロードしたいファイルを指定してください。<br>
        <input type="hidden" name="fileupload" value="submit"/>
        <input type="file" name="file" />
        <input type="submit" value="アップロード" />
    </form>
<%
    DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
    ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
    fileUpload.setHeaderEncoding("utf-8");    //ヘッダ情報の文字コード指定。ファイル名への対処
    try {
        for(FileItem item:(List<FileItem>)fileUpload.parseRequest(request)) {
            if(!item.isFormField()){
                String fileName = item.getName();
                if(fileName!=null&&fileName.length()>0){
                    out.println("ファイル名は「"+fileName+"」です。");
                    if(fileName.toLowerCase().endsWith(".txt")){
                        out.println("<br>テキストファイルなので以下に内容を表示します。");
                        out.println("<div style='border: 1px gray solid;padding:5px;'>"+item.getString("JISAutoDetect")+"</div>");    //ファイル自体の文字コード指定
                    }
                }
            }
        }
    }catch (Exception e) {
    }
%>
</body>
</html>

 ファイルアップロードの例2:ファイルリストの表示

  • ファイルの置き場所を作成し、アップロードされたファイルをその場所に追加していく。もし、すでにファイルがアップロードされている場合にはファイルリストを表示する。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="java.util.List"%>
<%@page import="java.io.File"%>
<%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
<%@page import="java.util.Date"%>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>ファイルのアップロード</title>
</head>
<body>
    <form action="${pageContext.request.requestURI}" method="post" enctype="multipart/form-data" >
        アップロードしたいファイルを指定してください。<br>
        <input type="hidden" name="fileupload" value="submit"/>
        <input type="file" name="file" />
        <input type="submit" value="アップロード" />
    </form>
<%
    String repositoryPath = getServletContext().getRealPath("WEB-INF/repository");
    File repository = new File(repositoryPath);
    if(!repository.exists()){    //リポジトリがなければ作成
        repository.mkdirs();
    }
    pageContext.setAttribute("repository",repository);
    DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
    ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
    fileUpload.setHeaderEncoding("utf-8");    //ヘッダ情報の文字コード指定。ファイル名への対処
    try {
        for(FileItem item:(List<FileItem>)fileUpload.parseRequest(request)) {
            if(!item.isFormField()){
                String fileName = item.getName();
                if(fileName!=null&&fileName.length()>0){
                    out.println("アップロードされたファイルは「"+fileName+"」です。");
                    if(fileName.toLowerCase().endsWith(".txt")){
                        out.println("<br>テキストファイルなので以下に内容を表示します。");
                        out.println("<div style='border: 1px gray solid;padding:5px;'>"+item.getString("JISAutoDetect")+"</div>");    //ファイル自体の文字コード指定
                    }
                }
                item.write(new File(repository.getAbsolutePath()+File.separator+(new File(fileName)).getName())); //ファイルの書き出し
            }
        }
    }catch (Exception e) {
    }
%>
    <hr>
    現在アップロードされているファイルリスト<br/>
    <small>(アップロードされた場所は${repository.absolutePath}になります)</small>
    <table border="1">
        <tr>
            <th>ファイル名</th>
            <th>サイズ(bytes)</th>
            <th>更新日</th>
        </tr>
<%
    for(File file:repository.listFiles()){
        out.print("<tr>"+
                "<td>"+file.getName()+"</td>"+
                "<td>"+file.length()+"</td>"+
                "<td>"+new Date(file.lastModified())+"</td>"+
                "</tr>");
    }
%>
        
        
    </table>
</body>
</html>

 ファイルアップロードの例3:アップロードされたファイルのダウンロード

  • ファイルの置き場所を作成し、アップロードされたファイルをその場所に追加していく。もし、すでにファイルがアップロードされている場合にはファイルリストを表示する。ファイルリストのファイル名部分にリンクを張り、そのリンクからファイルのダウンロードができる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@page import="java.util.List"%>
<%@page import="java.io.File"%>
<%@page import="java.io.FileInputStream"%>
<%@page import="java.util.Date"%>
<%@page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%    //初期化部分
    String repositoryPath = getServletContext().getRealPath("WEB-INF/repository");
    File repository = new File(repositoryPath);
    if(!repository.exists()){    //リポジトリがなければ作成
        repository.mkdirs();
    }
    //ファイルのダウンロード
    if(request.getParameter("download")!=null){     //パラメータ"download"があればファイルのダウンロード処理を行う
        File targetFile = new File(repositoryPath+File.separator+request.getParameter("file"));
        if(targetFile.exists()){    //ターゲットのファイルがあれば
            //mime-typeの設定
            response.setContentType(application.getMimeType(targetFile.getName()));
            //ファイル名の設定
            response.setHeader("Content-disposition", "attachment; filename=\""+targetFile.getName()+"\"");
            byte buffer[]  = new byte[4096];
            FileInputStream fis = new FileInputStream(targetFile);
            for(int size;(size = fis.read(buffer))!=-1;) {
                response.getOutputStream().write(buffer,0, size);
            }
            response.flushBuffer();
            return;
        }
    }
%>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>ファイルのアップロード</title>
</head>
<body>
    <form action="${pageContext.request.requestURI}" method="post" enctype="multipart/form-data" >
        アップロードしたいファイルを指定してください。<br>
        <input type="hidden" name="fileupload" value="submit"/>
        <input type="file" name="file" />
        <input type="submit" value="アップロード" />
    </form>
<%
    pageContext.setAttribute("repository",repository);
    DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
    ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
    fileUpload.setHeaderEncoding("utf-8");    //ヘッダ情報の文字コード指定。ファイル名への対処
    try {
        for(FileItem item:(List<FileItem>)fileUpload.parseRequest(request)) {
            if(!item.isFormField()){
                String fileName = item.getName();
                if(fileName!=null&&fileName.length()>0){
                    out.println("アップロードされたファイルは「"+fileName+"」です。");
                    if(fileName.toLowerCase().endsWith(".txt")){
                        out.println("<br>テキストファイルなので以下に内容を表示します。");
                        out.println("<div style='border: 1px gray solid;padding:5px;'>"+item.getString("JISAutoDetect")+"</div>");    //ファイル自体の文字コード指定
                    }
                }
                item.write(new File(repository.getAbsolutePath()+File.separator+(new File(fileName)).getName())); //ファイルの書き出し
            }
        }
    }catch (Exception e) {    //例外処理は省略
    }
%>
    <hr>
    現在アップロードされているファイルリスト<br/>
    <small>(アップロードされた場所は${repository.absolutePath}になります)</small>
    <table border="1">
        <tr>
            <th>ファイル名</th>
            <th>サイズ(bytes)</th>
            <th>更新日</th>
        </tr>
<%
    for(File file:repository.listFiles()){
%>
        <tr>
            <td><a href="${pageContext.request.requestURI}?download=true&file=<%=file.getName() %>" target="_blank"><%=file.getName() %></a></td>
            <td><%=file.length() %></td>
            <td><%=new Date(file.lastModified()) %></td>
        </tr>
<%
    }
%>
    </table>
</body>
</html>

 参考リンク


 課題

  1. ファイルアップロードの例2を改良し、ファイルの更新日を例えば"2009/01/18 10:05:04"("年/月/日 時:分:秒")という形で表示するようにしなさい。
  2. ファイルアップロードの例2を改良し、同じファイルをアップロードした場合にファイルの上書き確認をするようにしなさい。
FileUploadServlet.java fileUpload.jsp fileUpload02.jsp fileUpload03.jsp upload.jsp

最終更新時間:2013年07月02日 06時26分21秒