swithen colaco
swithen colaco

Reputation: 167

Uploading file with jetty and servlet

I am writing a java application to upload a file from browser. I am using jetty 9.4.15 and java servlet. When I upload the file, I get the below error message.

java.lang.IllegalStateException: No multipart config for servlet
at org.eclipse.jetty.server.Request.getParts(Request.java:2342)
at org.eclipse.jetty.server.Request.getParts(Request.java:2330)
at org.eclipse.jetty.server.Request.getPart(Request.java:2318)
at com.RekognizeServlet.doPost(RekognizeServlet.java:47)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:873)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:205)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:502)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:370)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:267)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:132)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.lang.Thread.run(Thread.java:745)

Below is the code I have written

SimplestServer.java

package com;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;


public class SimplestServer
{
    public static void main(String[] args) throws Exception
    {
    Server server = new Server(8080);

    ServletHandler handler = new ServletHandler();
    server.setHandler(handler);
    handler.addServletWithMapping(RekognizeServlet.class, "/tryAndRecognize");
    server.start();
    server.join();
}
}

RekognizeServlet.java

package com;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Collection;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

@MultipartConfig
public class RekognizeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

public RekognizeServlet() {
    super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html");
    response.setStatus(HttpServletResponse.SC_OK);
    response.getWriter().println("<!DOCTYPE html><html lang=\"en\"><head><title>File Upload</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"></head><body><form method=\"POST\" action=\"tryAndRecognize\" enctype=\"multipart/form-data\" >File:<input type=\"file\" name=\"file\" id=\"file\" /> <br/></br><input type=\"submit\" value=\"Upload\" name=\"upload\" id=\"upload\" /></form></body></html>");
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=UTF-8");

    // Create path components to save the file
    final String path = "/path/";
    final Part filePart = request.getPart("file");
    final Collection<Part> fileParts = request.getParts();
    final String fileName = getFileName(filePart);

    OutputStream out = null;
    InputStream filecontent = null;
    final PrintWriter writer = response.getWriter();

    try {
        out = new FileOutputStream(new File(path + File.separator + fileName));
        filecontent = filePart.getInputStream();

        int read = 0;
        final byte[] bytes = new byte[1024];

        while ((read = filecontent.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        System.out.println("File being uploaded to {1}");
    } catch (FileNotFoundException fne) {
        writer.println("You either did not specify a file to upload or are "
                + "trying to upload a file to a protected or nonexistent " + "location.");
        writer.println("<br/> ERROR: " + fne.getMessage());

        System.out.println("Problems during file upload");
        fne.printStackTrace();
    } finally {
        if (out != null) {
            out.close();
        }
        if (filecontent != null) {
            filecontent.close();
        }
        if (writer != null) {
            writer.close();
        }
    }
}

private String getFileName(final Part part) {
    final String partHeader = part.getHeader("content-disposition");
    System.out.println("Part Header = " + partHeader);
    for (String content : part.getHeader("content-disposition").split(";")) {
        if (content.trim().startsWith("filename")) {
            return content.substring(content.indexOf('=') + 1).trim().replace("\"", "");
        }
    }
    return null;
}

}

I am not using Handler like many examples online. Can anyone help?

Below are the links I have seen (not all)

How to implement FileUpload in embedded Jetty?

https://github.com/eclipse/jetty.project/issues/240

Upvotes: 0

Views: 2723

Answers (1)

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49545

Since you are using Embedded Jetty the bytecode scanning for annotations (such as @MultipartConfig) isn't enabled by default.

Enabling the bytecode scanning requires a lot of effort, it's actually easier to just specify in code what the annotations would actually do.

So, in your case, all you need to change is the initialization of your servlet.

Example:

Server server = new Server(8080);

ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");

ServletHolder uploadHolder = context.addServlet(RekognizeServlet.class,
        "/tryAndRecognize");

File tmpDir = new File(System.getProperty("java.io.tmpdir"));
File locationDir = new File(tmpDir, "jetty-fileupload");
if (!locationDir.exists()) locationDir.mkdirs();
String location = locationDir.getAbsolutePath();
long maxFileSize = 1024 * 1024 * 50;
long maxRequestSize = -1L;
int fileSizeThreshold = 1024 * 1024;
MultipartConfigElement multipartConfig = new MultipartConfigElement(location,
        maxFileSize, maxRequestSize, fileSizeThreshold);
uploadHolder.getRegistration().setMultipartConfig(multipartConfig);

server.setHandler(context);
server.start();

It's important to note that MultipartConfig needs at a location specified (as a bare minimum). Also, MultipartConfig will not work without a ServletContext, which the ServletContextHandler gives you.

Upvotes: 2

Related Questions