java Servlet&jsp で画像のアップロードファイルの作成が出来ません

投稿者: Anonymous

問題点・最終目的

java 初心者です。
jsp のフォームで受け取った画像ファイルを webサーバにアップロード・保存して、表示させる機能を作っています。
ネットやAPIを参考に、コードを書いていますが上手くアップロードファイルを作成することが出来ません。
現時点では、個人の開発環境なので自分のPC内のディレクトリからアップロードするファイルを選択する形ですが、本来は全く別のクライアントから画像を取得するプログラムを作成したいです。

開発環境

  • Eclipse(Version: 2019-03 (4.11.0), Tomcat9 , java11)
  • MacOS Mojave Version: 10.14.4

発生している例外

タイプ 例外報告

メッセージ /Applications/Eclipse_2019-03.app/Contents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/`upload_server/WEB-INF/upload/_1560801511375/img-landscape536x354.png`

例外

java.nio.file.`NoSuchFileException: `/Applications/Eclipse_2019-03.app/Contents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/upload_server/WEB-INF/upload/_1560801511375/img-landscape536x354.png
    java.base/sun.nio.fs.`UnixException.translateToIOException`(UnixException.java:92)
    java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
    java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:215)
    java.base/java.nio.file.Files.newByteChannel(Files.java:370)
    java.base/java.nio.file.Files.createFile(Files.java:647)
    (以下略)

  

試した事・その他原因として考えた事 等

・パス・ファイル名の取得方法を変える。
(はじめ、Part.getSubmittedFileName()を使っていた。)
・保存先ディレクトリを移動させる。
(権限の問題?という事でWebContent外へ)
 

そもそもパス、シンボリックリンク、サーバの保存先、フォームから得られる情報と形式、など基本的な事を理解できていなかったので、(今も完璧には理解できていない)
APIなどを参考に、例外に書き出しながらコードを書き換えトライしてみましたが上手くいきません。
権限の問題なのかとも思い調べて見ましたが(FileSystem等)直接的な解決策になるのかわかりませんでした。

一番不明瞭なのは、

String uploadDir=getServletContext().getRealPath("/WEB-INF/upload");

で、得られたパスのディレクトリにファイルを作れるのでしょうか。
…そこに作成するというのがそもそも間違いなのでしょうか。

何か根本的に間違っている点があるのだと思います。

初心者すぎて、ややこしい質問の仕方で申し訳ありません。
相当時間を費やしていて先に進めないので、どなたかご教示いただければ幸いです。
どうぞ宜しくお願いします。

以下、コードになります。
サーブレット

package servlet;

import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
(略)

public class FileUpload extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public FileUpload() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String path="/WEB-INF/jsp/fileUpload.jsp";

        RequestDispatcher dsp=request.getRequestDispatcher(path);
        dsp.forward(request, response);

        response.getWriter().append("Served at: ").append(request.getContextPath());
    }


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String title=request.getParameter("title");
    Part part=request.getPart("data");
    String nameadd=(new StringBuilder(title).append("_").append(System.currentTimeMillis()).toString());//オリジナルの名前にする

    String filename = new GetFileNameLogic().getFileName(part);
    
    String uploadDir=getServletContext().getRealPath("/WEB-INF/upload");
    Path file=Paths.get(uploadDir,nameadd,filename);
    try {
        Files.createFile(file);
    } catch (UnsupportedOperationException  e) {
        e.printStackTrace();
        throw new UnsupportedOperationException  ("原子的に設定できない属性が配列に含まれます");
    } catch (FileAlreadyExistsException e) {
        e.printStackTrace();
        throw new FileAlreadyExistsException ("同名ファイルがすでに存在します");
    }

    FileUploadLogic flogic =new FileUploadLogic ();
    try {
        flogic.execute(part, file);
    } catch (IOException e) {
        e.printStackTrace();
        throw new IOException("ファイル書き込み入出力エラー");
    }

    String to="/WEB-INF/result.jsp";
    RequestDispatcher dsp=request.getRequestDispatcher(to);
    dsp.forward(request, response);

    doGet(request, response);
  }
}

 
ファイル名を得るBO

package model;

import javax.servlet.http.Part;

public class GetFileNameLogic{
    public String getFileName(Part part) {
        String name= null;

        for (String dispotion : part.getHeader("Content-Disposition").split(";")) {
            if (dispotion.trim().startsWith("filename")) {
                 name = dispotion.substring(dispotion.indexOf("=") + 1).replace(""", "").trim();
                 name=name.substring(name.lastIndexOf("\")+1);

                 break;
            }
        }
        return name;
    }
}

アップロードのBO

package model;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;

import javax.servlet.http.Part;

public class FileUploadLogic {
        public void execute(Part part,Path path) throws IOException {
            File file=new File(path.toString());
            try(BufferedInputStream br=new BufferedInputStream(part.getInputStream());
                BufferedOutputStream bw=new BufferedOutputStream(new FileOutputStream(file))){
                int len=0;
                byte[] buff=new byte[(int)part.getSize()];
                while((len=br.read(buff)) != -1) {
                    bw.write(buff, 0, len);
                }
            }
        }
}



  

 

解決

String nameadd=(new StringBuilder(title).append("_").append(System.currentTimeMillis()).toString());//オリジナルの名前にする

これによって生成された名前(_1560801511375)のディレクトリーはOS上に存在しないはずです。存在しないディレクトリーにファイルを作成しようとして、NoSuchFileExceptionがスローされています。したがって、

Files.createFile(file);

の前に少なくとも以下のようにディレクトリーをつくっておかないと、正常に動作しないはずです。

Files.createDirectory(Paths.get(uploadDir,nameadd));
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *