user63762453
user63762453

Reputation: 1734

Unable to get the value of form fields when using enctype=multipart/form-data : java servlets

I have written this to upload an image in the specified folder and store the path in database, but when i click on add a blank page is displayed, I have already created all the folders in webcontent.I am using tomcat server:

My upload.jsp code looks something like this:

        <form action="Add" method=post enctype="multipart/form-data">
            <p>Book name:  <input type="text" name="bname" required/></p>
            <p>Price:<input type="text" name="bprice" required/></p>
            <p>Quantity:<input type="text" name="bqty" required/></p>
            <p>Image: <input type="file" name="file" required/></p>
            <p>Course: <select name="course">
            <option>course 1</option>
            <option>course 2</option> <!-- Some more options-->
            <input type="submit" value="Add" name="Submit"/></p>
        </form>

The Add.java servlet code is:

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


    response.setContentType("text/html");
    PrintWriter out=response.getWriter();

    String bname=request.getParameter("bname");
    String bprice=request.getParameter("bprice");
    String bqty=request.getParameter("bqty");
    String path="images";
    String file=request.getParameter("file");
    String course=request.getParameter("course");
    if(course.equals("course 1"))
    {
        path="images/folder1";
    }
    else if(course.equals("course 2"))
    {
        path="images/folder2";
    }
    else
    {
        path="images";
    }
    MultipartRequest m=new MultipartRequest(request,path);
    try
    {
        Class.forName("com.mysql.jdbc.Driver");
       Connection con=DriverManager.getConnection("",user,pass);

        PreparedStatement ps=con.prepareStatement("insert into product(bname,course,price,qty,path) values (?,?,?,?,?)");
        ps.setString(1,bname);      
        ps.setString(2,course);
        ps.setString(3,bprice); 
        ps.setString(4,bqty);   
        ps.setString(5,path+file);

        ps.executeUpdate();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }

    out.print("<p>Product added!</p>");

    RequestDispatcher rd=request.getRequestDispatcher("upload.jsp");
    rd.include(request, response);

}

I get NullPointer exception. I read somewhere that instead of using request.getParameter() I shoud use m.getParameter()

I did that and it worked, But that won't solve my problem because my code determines the path based on the value of course from the form.

And also I need to get the filename of the file uploaded, right now I am doing this like this: String file=request.getParameter("file");

I was trying some sample code and when I used m.getParameter() I managed to get values of all fields except file(I want that coz i want to store the img path in the DB). When I don't use enctype=multipart/form-data everything works fine (I also get the filename) except the error that content is multipart(That's obvious I know).

Upvotes: 0

Views: 8963

Answers (4)

kmario23
kmario23

Reputation: 61475

You can get both the form fields and the file using cos-multipart.jar.

The following worked for me:

public class FileUploadHandler extends HttpServlet {
    private final String UPLOAD_DIRECTORY = "/home/mario/Downloads";

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    //fix max file size 500 Mb
    int maxFileSize = 500000 * 1024;
    int maxMemSize = maxFileSize;

    //getting form fields (both text as well as file) (enctype=multipart/form-data)
    MultipartRequest mreq = new MultipartRequest(request, UPLOAD_DIRECTORY, maxFileSize);
    String uname = mreq.getParameter("username");  //give 'id' in html accordingly
    String dateofupload = mreq.getParameter("uploaddate"); 
    //System.out.println(uname);

    String NEW_UPLOAD_DIRECTORY = UPLOAD_DIRECTORY;

  //get actual file name here  //name field in html tag has to be given accordingly
    String uploadedfilename = mreq.getFilesystemName("file");

 //renaming & moving the file to new location
   File newfileloc = new File(NEW_UPLOAD_DIRECTORY + "/" + uploadedfilename);
   Boolean uploadresult = mreq.getFile("file").renameTo(newfileloc);  //true if success
  }
}

This initially saves the file to a location and rename/move it to new location. I could have saved it at the desired location but to do that I need file name, which comes only with the servlet request. But to access filename we need to create 'Multipart' request object. I tried to create two such things, one to access fields and the other to save file. But, cos-multipart.jar has some bugs in handling this.

Upvotes: 2

Sanjay
Sanjay

Reputation: 2503

try this way:


DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(MEMORY_THRESHOLD);
            factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setFileSizeMax(MAX_FILE_SIZE);
            upload.setSizeMax(MAX_REQUEST_SIZE); // sets maximum size of request (include file + form data)
            String uploadPath = getServletContext().getRealPath("") + File.separator + UPLOAD_DIRECTORY;

            File uploadDir = new File(uploadPath);
            if (!uploadDir.exists()) {
                uploadDir.mkdir();
            }

            List<FileItem> formItems = upload.parseRequest(request);

            if (formItems != null && formItems.size() > 0) {
                for (FileItem item : formItems) {
                    if (!item.isFormField()) {
                        //file field
                    } else {
                        other form field
                    }

Upvotes: 0

Jeroen
Jeroen

Reputation: 3146

You might want to consider using Apache commons FileUpload. It helps you handle these kinds of scenarios and handles most of the business logic for you.

When using Apache Commons FileUpload you can parse the request like this:

// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();

// Configure a repository (to ensure a secure temp location is used)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// Parse the request
List<FileItem> items = upload.parseRequest(request);

You can parse all the individual

// Process the uploaded items
Iterator<FileItem> iter = items.iterator();
while (iter.hasNext()) {
    FileItem item = iter.next();

    if (item.isFormField()) {
        processFormField(item);
    } else {
        processUploadedFile(item);
    }
}

Upvotes: 0

izstas
izstas

Reputation: 5064

ServletRequest#getParameter works only for application/x-www-form-urlencoded data (this encoding is used by default if you don't specify enctype attribute on your form). You can read more information about form content types here.

From the line

MultipartRequest m=new MultipartRequest(request,path);

I am assuming you are using the com.oreilly.servlet library.

In this case, using MultipartRequest#getParameter is a correct way to get the values of fields. In order to get the name of the uploaded file, you can use MultipartRequest#getFilesystemName.

my code determines the path based on the value of course from the form

I am afraid that you won't be able to do this in a clear way with com.oreilly.servlet library. What you could do is move the file by yourself like this:

m.getFile("file").renameTo(new File("newPath"));

Alternatively, you can consider using some other library for dealing with multipart data, such as Apache Commons FileUpload.

Upvotes: 2

Related Questions