18

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?

citizen conn
  • 15,011
  • 3
  • 54
  • 78
Clark Ku
  • 481
  • 2
  • 7
  • 10

5 Answers5

31

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);
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • 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... – Aniket Mar 21 '14 at 09:56
  • @Aniket: Just the same way as when you use a regular HTML form. – BalusC Mar 21 '14 at 10:55
12

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().

Nicolas Raoul
  • 55,003
  • 52
  • 197
  • 338
Hemant
  • 4,317
  • 8
  • 37
  • 41
2

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);

}
}
Bharti Gulati
  • 33
  • 1
  • 9
-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;
    }

}
Peter
  • 107
  • 1
  • 3
-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.

AlexR
  • 109,181
  • 14
  • 116
  • 194
  • 8
    Did you read the question? The code posted **is** the server side which already utilizes FileUpload. – BalusC Aug 02 '11 at 19:14