java.io.FileNotFoundException when writing uploaded file to disk via getRealPath()

chris loughnane picture chris loughnane · Feb 13, 2013 · Viewed 7.6k times · Source

Glassfish seems to be adding extra to the path I want to save my image file too, is there some way to use only the absolute path my servlet gets with

String appPath = request.getServletContext().getRealPath("");?

I have spent days trying different methods to upload an image file and have a servlet save it to disk.

I used this example: http://www.codejava.net/java-ee/servlet/how-to-write-upload-file-servlet-with-servlet-30-api

Using debug I can see the file name and path information is collected correctly but the code fails at `part.write(savePath + File.separator + fileName);``

And glassfish's exception report is:

exception

java.io.FileNotFoundException: C:\Program Files\glassfish-3.1.2.2\glassfish\domains\domain1\generated\jsp\com.onemore_onemore-web_war_1.0-SNAPSHOT\D:\Dropbox\Git\Brian_JEE\onemore\onemore\onemore-web\target\onemore-web-1.0-SNAPSHOT\image\screengrab_all_products.jpg (The filename, directory name, or volume label syntax is incorrect)

I can see the correct path as part of this exception D:\Dropbox\Git\Brian_JEE\onemore\onemore\onemore-web\target\onemore-web-1.0-SNAPSHOT\image\screengrab_all_products.jpg

JSP

<form action="${pageContext.request.contextPath}/imageupload" method="post" enctype="multipart/form-data" name="productForm" id="productForm">
<input type="file" name="file" id="file">
<input type="submit" name="Submit" value="Submit"></td>
</form>

Servlet

@WebServlet(name = "UploadImageServlet", urlPatterns = {"/imageupload"})
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, // 2MB 
maxFileSize = 1024 * 1024 * 10, // 10MB
maxRequestSize = 1024 * 1024 * 50)   // 50MB
public class UploadImageServlet extends HttpServlet {

    /**
     * Name of the directory where uploaded files will be saved, relative to the
     * web application directory.
     */
    private static final String SAVE_DIR = "image";

    /**
     * handles file upload
     */
    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
      // gets absolute path of the web application
        String appPath = request.getServletContext().getRealPath("");
        // constructs path of the directory to save uploaded file
        String savePath = appPath + File.separator + SAVE_DIR;

        // creates the save directory if it does not exists
        File fileSaveDir = new File(savePath);
        if (!fileSaveDir.exists()) {
            fileSaveDir.mkdir();
        }

        for (Part part : request.getParts()) {
            String fileName = extractFileName(part);
            part.write(savePath + File.separator + fileName);
        }

        request.setAttribute("message", "Upload has been done successfully!");
        getServletContext().getRequestDispatcher("/WEB-INF/jsp/newproduct.jsp").forward(
                request, response);
    }

    /**
     * Extracts file name from HTTP header content-disposition
     */
    private String extractFileName(Part part) {
        String contentDisp = part.getHeader("content-disposition");
        String[] items = contentDisp.split(";");
        for (String s : items) {
            if (s.trim().startsWith("filename")) {
                return s.substring(s.indexOf("=") + 2, s.length() - 1);
            }
        }
        return "";
    }
}

Answer

BalusC picture BalusC · Feb 13, 2013

Never use getRealPath()

You should not save uploaded files in the deploy folder. I have explained this so many times before. One of those explanations can be found in this answer: Uploaded image only available after refreshing the page.

Any JSP/Servlet code snippet found on some blog/article which ever uses the getRealPath() method should be taken with a huge bag of salt. Its quality and the knowledge of the author should strongly be questioned. There is namely no sensible real world use case for that method.

Save uploaded files in a fixed path outside the deploy folder. See also How do I set the folder for storing file uploads using Commons FileUpload.