Java Http Client to upload file over POST

Clark Ku picture Clark Ku · Aug 2, 2011 · Viewed 83.4k times · Source

I'm developing a J2ME client that must upload a file to a Servlet using HTTP.

The servlet part is covered using Apache Commons FileUpload

protected void doPost(HttpServletRequest request, HttpServletResponse response) 
{       

    ServletFileUpload upload = new ServletFileUpload();
    upload.setSizeMax(1000000);

    File fileItems = upload.parseRequest(request);

    // Process the uploaded items
    Iterator iter = fileItems.iterator();
    while (iter.hasNext()) {
        FileItem item = (FileItem) iter.next();
        File file = new File("\files\\"+item.getName());
        item.write(file);
    }
}

Commons Upload seems to be able to upload only multipart file, but no application/octect-stream.

But for the client side there are no Multipart classes, neither, in this case, is possible to use any HttpClient library.

Other option could be to use HTTP Chunk upload, but I haven't found a clear example of how this could be implemented, specially on the servlet side.

My choices are: - Implement a servlet for http chunk upload - Implement a raw client for http multipart creation

I don't know how to implement none of the above options. Any suggestion?

Answer

BalusC picture BalusC · Aug 2, 2011

Sending files over HTTP is supposed to take place using multipart/form-data encoding. Your servlet part is fine as it already uses Apache Commons FileUpload to parse a multipart/form-data request.

Your client part, however, is apparently not fine as you're seemingly writing the file content raw to the request body. You need to ensure that your client sends a proper multipart/form-data request. How exactly to do it depends on the API you're using to send the HTTP request. If it's plain vanilla java.net.URLConnection, then you can find a concrete example somewhere near the bottom of this answer. If you're using Apache HttpComponents Client for this, then here's a concrete example, taken from their documentation:

String url = "https://example.com";
File file = new File("/example.ext");

try (CloseableHttpClient client = HttpClients.createDefault()) {
    HttpPost post = new HttpPost(url);
    HttpEntity entity = MultipartEntityBuilder.create().addPart("file", new FileBody(file)).build();
    post.setEntity(entity);

    try (CloseableHttpResponse response = client.execute(post)) {
        // ...
    }
}

Unrelated to the concrete problem, there's a bug in your server side code:

File file = new File("\files\\"+item.getName());
item.write(file);

This will potentially overwrite any previously uploaded file with the same name. I'd suggest to use File#createTempFile() for this instead.

String name = FilenameUtils.getBaseName(item.getName());
String ext = FilenameUtils.getExtension(item.getName());
File file = File.createTempFile(name + "_", "." + ext, new File("/files"));
item.write(file);