Java Http Client to upload file over POST
Asked Answered
V

6

20

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?

Verse answered 2/8, 2011 at 18:55 Comment(0)
C
33

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. Although it is unnecessary since the Servlet 3.0-introduced request.getPart() method. See also How can I upload files to a server using JSP/Servlet?

Your client part, however, is not correct 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, based on 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);
Casi answered 2/8, 2011 at 19:13 Comment(2)
how can I get this file server side for example by using requset.getParameter we get string values so what about file from file body...Implicative
@Aniket: Just the same way as when you use a regular HTML form.Casi
G
13

Following code can be used to upload file with HTTP Client 4.x (Above answer uses MultipartEntity which is deprecated now)

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

String uploadFile(String url, File file) throws IOException
{
    HttpPost post = new HttpPost(url);
    post.setHeader("Accept", "application/json");
    _addAuthHeader(post);
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    // fileParamName should be replaced with parameter name your REST API expect.
    builder.addPart("fileParamName", new FileBody(file));
    //builder.addPart("optionalParam", new StringBody("true", ContentType.create("text/plain", Consts.ASCII)));
    post.setEntity(builder.build());
    HttpResponse response = getClient().execute(post);;
    int httpStatus = response.getStatusLine().getStatusCode();
    String responseMsg = EntityUtils.toString(response.getEntity(), "UTF-8");

    // If the returned HTTP response code is not in 200 series then
    // throw the error
    if (httpStatus < 200 || httpStatus > 300) {
        throw new IOException("HTTP " + httpStatus + " - Error during upload of file: " + responseMsg);
    }

    return responseMsg;
}

You will need recent versions of the following Apache libraries: httpclient, httpcore, httpmime.

getClient() can be replaced with HttpClients.createDefault().

Gob answered 30/1, 2018 at 17:46 Comment(0)
H
3

Please find the sample working example for File upload functionality using HttpClient in Java.

package test;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;

public class fileUpload {
private static void executeRequest(HttpPost httpPost) {
    try {
        HttpClient client = new DefaultHttpClient();
        HttpResponse response = client.execute(httpPost);
        System.out.println("Response Code:  " + response.getStatusLine().getStatusCode());
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void executeMultiPartRequest(String urlString, File file) throws IOException {
    HttpPost postRequest = new HttpPost(urlString);
    postRequest = addHeader(postRequest, "Access Token");
    try {
        postRequest.setEntity(new FileEntity(file));
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    executeRequest(postRequest);
}

private static HttpPost addHeader(HttpPost httpPost, String accessToken) {
    httpPost.addHeader("Accept", "application/json;odata=verbose");
    httpPost.setHeader("Authorization", "Bearer " + accessToken);
    return httpPost;
}

public static void main(String args[]) throws IOException {
    fileUpload fileUpload = new fileUpload();
    File file = new File("C:\\users\\bgulati\\Desktop\\test.docx");
    fileUpload.executeMultiPartRequest(
            "Here Goes the URL", file);

}
}
Hieratic answered 26/6, 2019 at 12:58 Comment(1)
thank you so much I've been looking for a long time on how to upload without the multipart entity w/apache's HttpClient. FileEntity is exactly what I needed for a non-binary file uploadLawana
B
0

Ancient question and best answer relies on incorrect statement.

Sending files over HTTP is supposed to take place using multipart/form-data encoding.

It is more efficient to send files as OCTET-STREAM.

Code for JDK11+ client:

HttpRequest request = HttpRequest.newBuilder()
    .uri(new URI("http://YOUR-SERVER:PORT/ENDPOINT"))
    .timeout(Duration.of(60, SECONDS))
    .POST(HttpRequest.BodyPublishers.ofInputStream(is))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
Bruyn answered 30/1, 2023 at 15:56 Comment(0)
U
-1

Thanks for all the code Ive sniped... Here is some back.

Gradle

compile "org.apache.httpcomponents:httpclient:4.4"  
compile "org.apache.httpcomponents:httpmime:4.4"



import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;


public class HttpClientUtils {

    public static String post(String postUrl, Map<String, String> params,
            Map<String, String> files) throws ClientProtocolException,
            IOException {
        CloseableHttpResponse response = null;
        InputStream is = null;
        String results = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();

        try {

            HttpPost httppost = new HttpPost(postUrl);

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();

            if (params != null) {
                for (String key : params.keySet()) {
                    StringBody value = new StringBody(params.get(key),
                            ContentType.TEXT_PLAIN);
                    builder.addPart(key, value);
                }
            }

            if (files != null && files.size() > 0) {
                for (String key : files.keySet()) {
                    String value = files.get(key);
                    FileBody body = new FileBody(new File(value));
                    builder.addPart(key, body);
                }
            }

            HttpEntity reqEntity = builder.build();
            httppost.setEntity(reqEntity);

            response = httpclient.execute(httppost);
            // assertEquals(200, response.getStatusLine().getStatusCode());

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                is = entity.getContent();
                StringWriter writer = new StringWriter();
                IOUtils.copy(is, writer, "UTF-8");
                results = writer.toString();
            }

        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            try {
                if (response != null) {
                    response.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            httpclient.close();
        }

        return results;
    }

    public static String get(String getStr) throws IOException,
            ClientProtocolException {
        CloseableHttpResponse response = null;
        InputStream is = null;
        String results = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();

        try {
            HttpGet httpGet = new HttpGet(getStr);
            response = httpclient.execute(httpGet);

            assertEquals(200, response.getStatusLine().getStatusCode());

            HttpEntity entity = response.getEntity();
            if (entity != null) {
                is = entity.getContent();
                StringWriter writer = new StringWriter();
                IOUtils.copy(is, writer, "UTF-8");
                results = writer.toString();
            }

        } finally {

            try {
                if (is != null) {
                    is.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            try {
                if (response != null) {
                    response.close();
                }
            } catch (Throwable t) {
                // No-op
            }

            httpclient.close();
        }

        return results;
    }

}
Urien answered 6/3, 2015 at 3:36 Comment(0)
A
-2

Without entering to gory details your code looks fine.

Now you need the server side. I'd recommend you to use Jakarta FileUpload, so you do not have to implement anything. Just deploy and configure.

Adobe answered 2/8, 2011 at 19:0 Comment(1)
Did you read the question? The code posted is the server side which already utilizes FileUpload.Casi

© 2022 - 2024 — McMap. All rights reserved.