Upload files from Java client to a HTTP server - java

I'd like to upload a few files to a HTTP server. Basically what I need is some sort of a POST request to the server with a few parameters and the files. I've seen examples of just uploading files, but didn't find how to also pass additional parameters.
What's the simplest and free solution of doing this? Does anyone have any file upload examples that I could study? I've been googling for a few hours, but (maybe it's just one of those days) couldn't find exactly what I needed. The best solution would be something that doesn't involve any third party classes or libraries.

You'd normally use java.net.URLConnection to fire HTTP requests. You'd also normally use multipart/form-data encoding for mixed POST content (binary and character data). Click the link, it contains information and an example how to compose a multipart/form-data request body. The specification is in more detail described in RFC2388.
Here's a kickoff example:
String url = "http://example.com/upload";
String charset = "UTF-8";
String param = "value";
File textFile = new File("/path/to/file.txt");
File binaryFile = new File("/path/to/file.bin");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
) {
// Send normal param.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF).append(param).append(CRLF).flush();
// Send text file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); // Text file itself must be saved in this charset!
writer.append(CRLF).flush();
Files.copy(textFile.toPath(), output);
output.flush(); // Important before continuing with writer!
writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.
// Send binary file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(binaryFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(binaryFile.toPath(), output);
output.flush(); // Important before continuing with writer!
writer.append(CRLF).flush(); // CRLF is important! It indicates end of boundary.
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF).flush();
}
// Request is lazily fired whenever you need to obtain information about response.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println(responseCode); // Should be 200
This code is less verbose when you use a 3rd party library like Apache Commons HttpComponents Client.
The Apache Commons FileUpload as some incorrectly suggest here is only of interest in the server side. You can't use and don't need it at the client side.
See also
Using java.net.URLConnection to fire and handle HTTP requests

Here is how you would do it with Apache HttpClient (this solution is for those who don't mind using a 3rd party library):
HttpEntity entity = MultipartEntityBuilder.create()
.addPart("file", new FileBody(file))
.build();
HttpPost request = new HttpPost(url);
request.setEntity(entity);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);

click link get example file upload clint java with apache HttpComponents
http://hc.apache.org/httpcomponents-client-ga/httpmime/examples/org/apache/http/examples/entity/mime/ClientMultipartFormPost.java
and library downalod link
https://hc.apache.org/downloads.cgi
use 4.5.3.zip it's working fine in my code
and my working code..
import java.io.File;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
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;
import org.apache.http.util.EntityUtils;
public class ClientMultipartFormPost {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost("http://localhost:8080/MyWebSite1/UploadDownloadFileServlet");
FileBody bin = new FileBody(new File("E:\\meter.jpg"));
StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);
HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("bin", bin)
.addPart("comment", comment)
.build();
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}

Here is how you could do it with Java 11's java.net.http package:
var fileA = new File("a.pdf");
var fileB = new File("b.pdf");
var mimeMultipartData = MimeMultipartData.newBuilder()
.withCharset(StandardCharsets.UTF_8)
.addFile("file1", fileA.toPath(), Files.probeContentType(fileA.toPath()))
.addFile("file2", fileB.toPath(), Files.probeContentType(fileB.toPath()))
.build();
var request = HttpRequest.newBuilder()
.header("Content-Type", mimeMultipartData.getContentType())
.POST(mimeMultipartData.getBodyPublisher())
.uri(URI.create("http://somehost/upload"))
.build();
var httpClient = HttpClient.newBuilder().build();
var response = httpClient.send(request, BodyHandlers.ofString());
With the following MimeMultipartData:
public class MimeMultipartData {
public static class Builder {
private String boundary;
private Charset charset = StandardCharsets.UTF_8;
private List<MimedFile> files = new ArrayList<MimedFile>();
private Map<String, String> texts = new LinkedHashMap<>();
private Builder() {
this.boundary = new BigInteger(128, new Random()).toString();
}
public Builder withCharset(Charset charset) {
this.charset = charset;
return this;
}
public Builder withBoundary(String boundary) {
this.boundary = boundary;
return this;
}
public Builder addFile(String name, Path path, String mimeType) {
this.files.add(new MimedFile(name, path, mimeType));
return this;
}
public Builder addText(String name, String text) {
texts.put(name, text);
return this;
}
public MimeMultipartData build() throws IOException {
MimeMultipartData mimeMultipartData = new MimeMultipartData();
mimeMultipartData.boundary = boundary;
var newline = "\r\n".getBytes(charset);
var byteArrayOutputStream = new ByteArrayOutputStream();
for (var f : files) {
byteArrayOutputStream.write(("--" + boundary).getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(("Content-Disposition: form-data; name=\"" + f.name + "\"; filename=\"" + f.path.getFileName() + "\"").getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(("Content-Type: " + f.mimeType).getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(Files.readAllBytes(f.path));
byteArrayOutputStream.write(newline);
}
for (var entry: texts.entrySet()) {
byteArrayOutputStream.write(("--" + boundary).getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"").getBytes(charset));
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(newline);
byteArrayOutputStream.write(entry.getValue().getBytes(charset));
byteArrayOutputStream.write(newline);
}
byteArrayOutputStream.write(("--" + boundary + "--").getBytes(charset));
mimeMultipartData.bodyPublisher = BodyPublishers.ofByteArray(byteArrayOutputStream.toByteArray());
return mimeMultipartData;
}
public class MimedFile {
public final String name;
public final Path path;
public final String mimeType;
public MimedFile(String name, Path path, String mimeType) {
this.name = name;
this.path = path;
this.mimeType = mimeType;
}
}
}
private String boundary;
private BodyPublisher bodyPublisher;
private MimeMultipartData() {
}
public static Builder newBuilder() {
return new Builder();
}
public BodyPublisher getBodyPublisher() throws IOException {
return bodyPublisher;
}
public String getContentType() {
return "multipart/form-data; boundary=" + boundary;
}
}

public static String simSearchByImgURL(int catid ,String imgurl) throws IOException{
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String result =null;
try {
HttpPost httppost = new HttpPost("http://api0.visualsearchapi.com:8084/vsearchtech/api/v1.0/apisim_search");
StringBody catidBody = new StringBody(catid+"" , ContentType.TEXT_PLAIN);
StringBody keyBody = new StringBody(APPKEY , ContentType.TEXT_PLAIN);
StringBody langBody = new StringBody(LANG , ContentType.TEXT_PLAIN);
StringBody fmtBody = new StringBody(FMT , ContentType.TEXT_PLAIN);
StringBody imgurlBody = new StringBody(imgurl , ContentType.TEXT_PLAIN);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addPart("apikey", keyBody).addPart("catid", catidBody)
.addPart("lang", langBody)
.addPart("fmt", fmtBody)
.addPart("imgurl", imgurlBody);
HttpEntity reqEntity = builder.build();
httppost.setEntity(reqEntity);
response = httpClient.execute(httppost);
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
// result = ConvertStreamToString(resEntity.getContent(), "UTF-8");
String charset = "UTF-8";
String content=EntityUtils.toString(response.getEntity(), charset);
System.out.println(content);
}
EntityUtils.consume(resEntity);
}catch(Exception e){
e.printStackTrace();
}finally {
response.close();
httpClient.close();
}
return result;
}

I suggest to use Apache http classes instead of Vanilla Java. This is a Java 8 compatible simple solution:
// Create http client.
CloseableHttpClient httpClient = HttpClients.createDefault();
final File file = new File("<FILE PATH TO POST>");
// Specify the content type of the attached file.
FileBody filebody = new FileBody(file, ContentType.MULTIPART_FORM_DATA);
MultipartEntityBuilder entitybuilder = MultipartEntityBuilder.create();
entitybuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// Add the binary file to the entity we send later on.
entitybuilder.addBinaryBody("file", file);
HttpEntity mutiPartHttpEntity = entitybuilder.build();
RequestBuilder reqbuilder = RequestBuilder.post("URL TO POST DATA WITH ALL THE PARAMETERS");
reqbuilder.setEntity(mutiPartHttpEntity);
HttpUriRequest multipartRequest = reqbuilder.build();
// Using the http client, execute http post. Variable httpresponse would contain the reply back explaining http response code, and ...
HttpResponse httpresponse = httpClient.execute(multipartRequest);
httpClient.close();
In order to embed the parameters to the post message, you can simply embed them in the URL used to post data. Use this rule: ?=&=. An example would be the following:
https://company.com/jobs/status?jobId=876&apiKey=123
To find out which data type suites your file which is posted with Http post, see this link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
Import packages of org.apache.http.*
In case importing did not work, you might need to change pom.xml file (if you are using Maven) and add the Apache package to this xml file. See this.

protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
return;
}
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(MAX_MEMORY_SIZE);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
String uploadFolder = getServletContext().getRealPath("")
+ File.separator + DATA_DIRECTORY;//DATA_DIRECTORY is directory where you upload this file on the server
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(MAX_REQUEST_SIZE);//MAX_REQUEST_SIZE is the size which size you prefer
And use <form enctype="multipart/form-data"> and use <input type="file"> in the html

It could depend on your framework. (for each of them could exist an easier solution).
But to answer your question: there are a lot of external libraries for this functionality. Look here how to use apache commons fileupload.

Related

Microsoft graph : Updating a document with a Put request Java

Based on the MS graph documentation, I saw that i can update a driveItem (file) and put it in a specific sharepoint drive. The application is running as a daemon application (without user login).
For this I use this entry point :
PUT /drives/{drive-id}/items/{item-id}/content
I try to code using a main class and passing existing parameters. To update a document I call a method update document :
UpdateDocumentResponseModel updatedDocument = fileGraphs.updateDocument(token, DRIVELIBID, DOCUMENTID, INPUTPATH, DOCUPDATE);
The called method aims to build the URL and prepare the datas for the PUT request :
public UpdateDocumentResponseModel updateDocument(String accessToken,
String driveLibId,
String documentId,
String inpuPath,
String docName) throws MalformedURLException {
String fullPath = inpuPath + docName;
URL url = new URL("https://graph.microsoft.com/v1.0/drives/" + driveLibId + "/items/" + documentId + "/content");
return requestsBuilder.updateDocument(accessToken, url, fullPath);
}
Now at this stage I have to make the request:
public UpdateDocumentResponseModel updateDocument(String accessToken, URL url, String fullPath) {
UpdateDocumentResponseModel returnValue = new UpdateDocumentResponseModel();
try {
CloseableHttpClient client = HttpClients.createDefault();
HttpPut httpPut = new HttpPut(String.valueOf(url));
httpPut.setHeader("Authorization", "Bearer " + accessToken);
httpPut.setHeader("Accept","application/json");
httpPut.setHeader("Content-Type","plain/text");
httpPut.setHeader("Connection", "Keep-Alive");
httpPut.setHeader("Cache-Control", "no-cache");
// read the file and convert to stream
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File(fullPath),
ContentType.APPLICATION_OCTET_STREAM, "file.ext");
HttpEntity multipart = builder.build();
httpPut.setEntity(multipart);
CloseableHttpResponse response = client.execute(httpPut);
System.out.println("\nSending 'UPDATE' request to URL : " + url);
System.out.println("Response Code : " + response.getStatusLine());
// set the response
returnValue.setDocumentName(fullPath);
returnValue.setUpdatedAt(new Date());
returnValue.setUpdateStatus("Success");
} catch (IOException e) {
returnValue.setDocumentName(fullPath);
returnValue.setUpdatedAt(new Date());
returnValue.setUpdateStatus("Failure" + e.getCause());
e.printStackTrace();
}
return returnValue;
}
My issue is that when I send back a docx file, this file is not correctly uploaded. The file is uploaded (good stuff) but is not readable in the sharepoint online portal and must be downloaded.
My second issue is that I can take any kind of file : doc, docx, ppt, xls, xlsx, txt, images...
I do think that I will encounter other issues. Is there a lib that could help me to handle file extension and correctly convert files. My issue is that I won't have to handle specifically MS Office files but any types.
My issue is obviously here :
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File(fullPath),
ContentType.APPLICATION_OCTET_STREAM, "file.ext");
HttpEntity multipart = builder.build();
httpPut.setEntity(multipart);
CloseableHttpResponse response = client.execute(httpPut);
Thanks !
I finally solved the issue by using ByteArrayInputStream...
I replaced :
// read the file and convert to stream
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", new File(fullPath),
ContentType.APPLICATION_OCTET_STREAM, "file.ext");
HttpEntity multipart = builder.build();
httpPut.setEntity(multipart);
with this:
byte[] fileContent = FileUtils.readFileToByteArray(new File(fullPath));
httpPut.setEntity(new InputStreamEntity(new ByteArrayInputStream(fileContent), fileContent.length));
Finally my method looks like this :
public UpdateDocumentResponseModel updateDocument(String accessToken, URL url, String fullPath) {
UpdateDocumentResponseModel returnValue = new UpdateDocumentResponseModel();
try {
CloseableHttpClient client = HttpClients.createDefault();
HttpPut httpPut = new HttpPut(String.valueOf(url));
httpPut.setHeader("Authorization", "Bearer " + accessToken);
httpPut.setHeader("Content-Type", "text/plain");
httpPut.setHeader("Connection", "Keep-Alive");
httpPut.setHeader("Cache-Control", "no-cache");
byte[] fileContent = FileUtils.readFileToByteArray(new File(fullPath));
httpPut.setEntity(new InputStreamEntity(new ByteArrayInputStream(fileContent), fileContent.length));
// httpPut.setEntity(new StringEntity(String.valueOf(in), StandardCharsets.UTF_8));
CloseableHttpResponse response = client.execute(httpPut);
System.out.println("\nSending 'PUT' request to URL : " + url);
System.out.println("Response Code : " + response.getStatusLine());
// set the response
returnValue.setDocumentName(fullPath);
returnValue.setUpdatedAt(new Date());
returnValue.setUpdateStatus("Success");
} catch (IOException e) {
returnValue.setDocumentName(fullPath);
returnValue.setUpdatedAt(new Date());
returnValue.setUpdateStatus("Failure" + e.getCause());
e.printStackTrace();
}
return returnValue;
}

How to convert this cUrl command to java containing form and binary data [duplicate]

In the days of version 3.x of Apache Commons HttpClient, making a multipart/form-data POST request was possible (an example from 2004). Unfortunately this is no longer possible in version 4.0 of HttpClient.
For our core activity "HTTP", multipart is somewhat
out of scope. We'd love to use multipart code maintained by some
other project for which it is in scope, but I'm not aware of any.
We tried to move the multipart code to commons-codec a few years
ago, but I didn't take off there. Oleg recently mentioned another
project that has multipart parsing code and might be interested
in our multipart formatting code. I don't know the current status
on that. (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)
Is anybody aware of any Java library that allows me to write an HTTP client that can make a multipart/form-data POST request?
Background: I want to use the Remote API of Zoho Writer.
We use HttpClient 4.x to make multipart file post.
UPDATE: As of HttpClient 4.3, some classes have been deprecated. Here is the code with new API:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("...");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("field1", "yes", ContentType.TEXT_PLAIN);
// This attaches the file to the POST:
File f = new File("[/path/to/upload]");
builder.addBinaryBody(
"file",
new FileInputStream(f),
ContentType.APPLICATION_OCTET_STREAM,
f.getName()
);
HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
CloseableHttpResponse response = httpClient.execute(uploadFile);
HttpEntity responseEntity = response.getEntity();
Below is the original snippet of code with deprecated HttpClient 4.0 API:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
FileBody bin = new FileBody(new File(fileName));
StringBody comment = new StringBody("Filename: " + fileName);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("bin", bin);
reqEntity.addPart("comment", comment);
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
These are the Maven dependencies I have.
Java Code:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
FileBody uploadFilePart = new FileBody(uploadFile);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload-file", uploadFilePart);
httpPost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httpPost);
Maven Dependencies in pom.xml:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.0.1</version>
<scope>compile</scope>
</dependency>
If size of the JARs matters (e.g. in case of applet), one can also directly use httpmime with java.net.HttpURLConnection instead of HttpClient.
httpclient-4.2.4: 423KB
httpmime-4.2.4: 26KB
httpcore-4.2.4: 222KB
commons-codec-1.6: 228KB
commons-logging-1.1.1: 60KB
Sum: 959KB
httpmime-4.2.4: 26KB
httpcore-4.2.4: 222KB
Sum: 248KB
Code:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
FileBody fileBody = new FileBody(new File(fileName));
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT);
multipartEntity.addPart("file", fileBody);
connection.setRequestProperty("Content-Type", multipartEntity.getContentType().getValue());
OutputStream out = connection.getOutputStream();
try {
multipartEntity.writeTo(out);
} finally {
out.close();
}
int status = connection.getResponseCode();
...
Dependency in pom.xml:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.2.4</version>
</dependency>
Use this code to upload images or any other files to the server using post in multipart.
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
public class SimplePostRequestTest {
public static void main(String[] args) throws UnsupportedEncodingException, IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.0.102/uploadtest/upload_photo");
try {
FileBody bin = new FileBody(new File("/home/ubuntu/cd.png"));
StringBody id = new StringBody("3");
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload_image", bin);
reqEntity.addPart("id", id);
reqEntity.addPart("image_title", new StringBody("CoolPic"));
httppost.setEntity(reqEntity);
System.out.println("Requesting : " + httppost.getRequestLine());
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httppost, responseHandler);
System.out.println("responseBody : " + responseBody);
} catch (ClientProtocolException e) {
} finally {
httpclient.getConnectionManager().shutdown();
}
}
}
it requires below files to upload.
libraries are
httpclient-4.1.2.jar,
httpcore-4.1.2.jar,
httpmime-4.1.2.jar,
httpclient-cache-4.1.2.jar,
commons-codec.jar and
commons-logging-1.1.1.jar to be in classpath.
Here's a solution that does not require any libraries.
This routine transmits every file in the directory d:/data/mpf10 to urlToConnect
String boundary = Long.toHexString(System.currentTimeMillis());
URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
File dir = new File("d:/data/mpf10");
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
continue;
}
writer.println("--" + boundary);
writer.println("Content-Disposition: form-data; name=\"" + file.getName() + "\"; filename=\"" + file.getName() + "\"");
writer.println("Content-Type: text/plain; charset=UTF-8");
writer.println();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
for (String line; (line = reader.readLine()) != null;) {
writer.println(line);
}
} finally {
if (reader != null) {
reader.close();
}
}
}
writer.println("--" + boundary + "--");
} finally {
if (writer != null) writer.close();
}
// Connection is lazily executed whenever you request any status.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
// Handle response
You can also use REST Assured which builds on HTTP Client. It's very simple:
given().multiPart(new File("/somedir/file.bin")).when().post("/fileUpload");
httpcomponents-client-4.0.1 worked for me. However, I had to add the external jar apache-mime4j-0.6.jar (org.apache.james.mime4j) otherwise
reqEntity.addPart("bin", bin); would not compile. Now it's working like charm.
I found this sample in Apache's Quickstart Guide. It's for version 4.5:
/**
* Example how to use multipart/form encoded POST request.
*/
public class ClientMultipartFormPost {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("File path not given");
System.exit(1);
}
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost("http://localhost:8080" +
"/servlets-examples/servlet/RequestInfoExample");
FileBody bin = new FileBody(new File(args[0]));
StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);
HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("bin", bin)
.addPart("comment", comment)
.build();
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
You will happy!
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3.1</version>
</dependency>
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
byte[] byteArr1 = multipartFile1.getBytes();
byte[] byteArr2 = multipartFile2.getBytes();
HttpEntity reqEntity = MultipartEntityBuilder.create().setCharset(Charset.forName("UTF-8"))
.addPart("image1", new ByteArrayBody(byteArr1, req.getMultipartFile1().getOriginalFilename()))
.addPart("image2", new ByteArrayBody(byteArr2, req.getMultipartFile2().getOriginalFilename()))
.build();
We have a pure java implementation of multipart-form submit without using any external dependencies or libraries outside jdk. Refer https://github.com/atulsm/https-multipart-purejava/blob/master/src/main/java/com/atul/MultipartPure.java
private static String body = "{\"key1\":\"val1\", \"key2\":\"val2\"}";
private static String subdata1 = "## -2,3 +2,4 ##\r\n";
private static String subdata2 = "<data>subdata2</data>";
public static void main(String[] args) throws Exception{
String url = "https://" + ip + ":" + port + "/dataupload";
String token = "Basic "+ Base64.getEncoder().encodeToString((userName+":"+password).getBytes());
MultipartBuilder multipart = new MultipartBuilder(url,token);
multipart.addFormField("entity", "main", "application/json",body);
multipart.addFormField("attachment", "subdata1", "application/octet-stream",subdata1);
multipart.addFormField("attachment", "subdata2", "application/octet-stream",subdata2);
List<String> response = multipart.finish();
for (String line : response) {
System.out.println(line);
}
}
My code post multipartFile to server.
public static HttpResponse doPost(
String host,
String path,
String method,
MultipartFile multipartFile
) throws IOException
{
HttpClient httpClient = wrapClient(host);
HttpPost httpPost = new HttpPost(buildUrl(host, path));
if (multipartFile != null) {
HttpEntity httpEntity;
ContentBody contentBody;
contentBody = new ByteArrayBody(multipartFile.getBytes(), multipartFile.getOriginalFilename());
httpEntity = MultipartEntityBuilder.create()
.addPart("nameOfMultipartFile", contentBody)
.build();
httpPost.setEntity(httpEntity);
}
return httpClient.execute(httpPost);
}
My code for sending files to server using post in multipart.
Make use of multivalue map while making request for sending form data
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("FILE", new FileSystemResource(file));
map.add("APPLICATION_ID", Number);
httpService.post( map,headers);
At receiver end use
#RequestMapping(value = "fileUpload", method = RequestMethod.POST)
public ApiResponse AreaCsv(#RequestParam("FILE") MultipartFile file,#RequestHeader("clientId") ){
//code
}
Using HttpRequestFactory to jira xray's /rest/raven/1.0/import/execution/cucumber/multipart :
Map<String, Object> params = new HashMap<>();
params.put( "info", "zigouzi" );
params.put( "result", "baalo" );
HttpContent content = new UrlEncodedContent(params);
OAuthParameters oAuthParameters = jiraOAuthFactory.getParametersForRequest(ACCESS_TOKEN, CONSUMER_KEY, PRIVATE_KEY);
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(oAuthParameters);
HttpRequest request = requestFactory.buildPostRequest(new GenericUrl(url), content);
request.getHeaders().setAccept("application/json");
String boundary = Long.toHexString(System.currentTimeMillis());
request.getHeaders().setContentType("multipart/form-data; boundary="+boundary);
request.getHeaders().setContentEncoding("application/json");
HttpResponse response = null ;
try
{
response = request.execute();
Scanner s = new Scanner(response.getContent()).useDelimiter("\\A");
result = s.hasNext() ? s.next() : "";
}
catch (Exception e)
{
}
did the trick.

Send an image from Google Glass to a HTTP server [duplicate]

In the days of version 3.x of Apache Commons HttpClient, making a multipart/form-data POST request was possible (an example from 2004). Unfortunately this is no longer possible in version 4.0 of HttpClient.
For our core activity "HTTP", multipart is somewhat
out of scope. We'd love to use multipart code maintained by some
other project for which it is in scope, but I'm not aware of any.
We tried to move the multipart code to commons-codec a few years
ago, but I didn't take off there. Oleg recently mentioned another
project that has multipart parsing code and might be interested
in our multipart formatting code. I don't know the current status
on that. (http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html)
Is anybody aware of any Java library that allows me to write an HTTP client that can make a multipart/form-data POST request?
Background: I want to use the Remote API of Zoho Writer.
We use HttpClient 4.x to make multipart file post.
UPDATE: As of HttpClient 4.3, some classes have been deprecated. Here is the code with new API:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("...");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("field1", "yes", ContentType.TEXT_PLAIN);
// This attaches the file to the POST:
File f = new File("[/path/to/upload]");
builder.addBinaryBody(
"file",
new FileInputStream(f),
ContentType.APPLICATION_OCTET_STREAM,
f.getName()
);
HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
CloseableHttpResponse response = httpClient.execute(uploadFile);
HttpEntity responseEntity = response.getEntity();
Below is the original snippet of code with deprecated HttpClient 4.0 API:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
FileBody bin = new FileBody(new File(fileName));
StringBody comment = new StringBody("Filename: " + fileName);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("bin", bin);
reqEntity.addPart("comment", comment);
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
These are the Maven dependencies I have.
Java Code:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
FileBody uploadFilePart = new FileBody(uploadFile);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload-file", uploadFilePart);
httpPost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httpPost);
Maven Dependencies in pom.xml:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.0.1</version>
<scope>compile</scope>
</dependency>
If size of the JARs matters (e.g. in case of applet), one can also directly use httpmime with java.net.HttpURLConnection instead of HttpClient.
httpclient-4.2.4: 423KB
httpmime-4.2.4: 26KB
httpcore-4.2.4: 222KB
commons-codec-1.6: 228KB
commons-logging-1.1.1: 60KB
Sum: 959KB
httpmime-4.2.4: 26KB
httpcore-4.2.4: 222KB
Sum: 248KB
Code:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
FileBody fileBody = new FileBody(new File(fileName));
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT);
multipartEntity.addPart("file", fileBody);
connection.setRequestProperty("Content-Type", multipartEntity.getContentType().getValue());
OutputStream out = connection.getOutputStream();
try {
multipartEntity.writeTo(out);
} finally {
out.close();
}
int status = connection.getResponseCode();
...
Dependency in pom.xml:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.2.4</version>
</dependency>
Use this code to upload images or any other files to the server using post in multipart.
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
public class SimplePostRequestTest {
public static void main(String[] args) throws UnsupportedEncodingException, IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.0.102/uploadtest/upload_photo");
try {
FileBody bin = new FileBody(new File("/home/ubuntu/cd.png"));
StringBody id = new StringBody("3");
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload_image", bin);
reqEntity.addPart("id", id);
reqEntity.addPart("image_title", new StringBody("CoolPic"));
httppost.setEntity(reqEntity);
System.out.println("Requesting : " + httppost.getRequestLine());
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httppost, responseHandler);
System.out.println("responseBody : " + responseBody);
} catch (ClientProtocolException e) {
} finally {
httpclient.getConnectionManager().shutdown();
}
}
}
it requires below files to upload.
libraries are
httpclient-4.1.2.jar,
httpcore-4.1.2.jar,
httpmime-4.1.2.jar,
httpclient-cache-4.1.2.jar,
commons-codec.jar and
commons-logging-1.1.1.jar to be in classpath.
Here's a solution that does not require any libraries.
This routine transmits every file in the directory d:/data/mpf10 to urlToConnect
String boundary = Long.toHexString(System.currentTimeMillis());
URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
File dir = new File("d:/data/mpf10");
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
continue;
}
writer.println("--" + boundary);
writer.println("Content-Disposition: form-data; name=\"" + file.getName() + "\"; filename=\"" + file.getName() + "\"");
writer.println("Content-Type: text/plain; charset=UTF-8");
writer.println();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
for (String line; (line = reader.readLine()) != null;) {
writer.println(line);
}
} finally {
if (reader != null) {
reader.close();
}
}
}
writer.println("--" + boundary + "--");
} finally {
if (writer != null) writer.close();
}
// Connection is lazily executed whenever you request any status.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
// Handle response
You can also use REST Assured which builds on HTTP Client. It's very simple:
given().multiPart(new File("/somedir/file.bin")).when().post("/fileUpload");
httpcomponents-client-4.0.1 worked for me. However, I had to add the external jar apache-mime4j-0.6.jar (org.apache.james.mime4j) otherwise
reqEntity.addPart("bin", bin); would not compile. Now it's working like charm.
I found this sample in Apache's Quickstart Guide. It's for version 4.5:
/**
* Example how to use multipart/form encoded POST request.
*/
public class ClientMultipartFormPost {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("File path not given");
System.exit(1);
}
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost("http://localhost:8080" +
"/servlets-examples/servlet/RequestInfoExample");
FileBody bin = new FileBody(new File(args[0]));
StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);
HttpEntity reqEntity = MultipartEntityBuilder.create()
.addPart("bin", bin)
.addPart("comment", comment)
.build();
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
You will happy!
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3.1</version>
</dependency>
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
byte[] byteArr1 = multipartFile1.getBytes();
byte[] byteArr2 = multipartFile2.getBytes();
HttpEntity reqEntity = MultipartEntityBuilder.create().setCharset(Charset.forName("UTF-8"))
.addPart("image1", new ByteArrayBody(byteArr1, req.getMultipartFile1().getOriginalFilename()))
.addPart("image2", new ByteArrayBody(byteArr2, req.getMultipartFile2().getOriginalFilename()))
.build();
We have a pure java implementation of multipart-form submit without using any external dependencies or libraries outside jdk. Refer https://github.com/atulsm/https-multipart-purejava/blob/master/src/main/java/com/atul/MultipartPure.java
private static String body = "{\"key1\":\"val1\", \"key2\":\"val2\"}";
private static String subdata1 = "## -2,3 +2,4 ##\r\n";
private static String subdata2 = "<data>subdata2</data>";
public static void main(String[] args) throws Exception{
String url = "https://" + ip + ":" + port + "/dataupload";
String token = "Basic "+ Base64.getEncoder().encodeToString((userName+":"+password).getBytes());
MultipartBuilder multipart = new MultipartBuilder(url,token);
multipart.addFormField("entity", "main", "application/json",body);
multipart.addFormField("attachment", "subdata1", "application/octet-stream",subdata1);
multipart.addFormField("attachment", "subdata2", "application/octet-stream",subdata2);
List<String> response = multipart.finish();
for (String line : response) {
System.out.println(line);
}
}
My code post multipartFile to server.
public static HttpResponse doPost(
String host,
String path,
String method,
MultipartFile multipartFile
) throws IOException
{
HttpClient httpClient = wrapClient(host);
HttpPost httpPost = new HttpPost(buildUrl(host, path));
if (multipartFile != null) {
HttpEntity httpEntity;
ContentBody contentBody;
contentBody = new ByteArrayBody(multipartFile.getBytes(), multipartFile.getOriginalFilename());
httpEntity = MultipartEntityBuilder.create()
.addPart("nameOfMultipartFile", contentBody)
.build();
httpPost.setEntity(httpEntity);
}
return httpClient.execute(httpPost);
}
My code for sending files to server using post in multipart.
Make use of multivalue map while making request for sending form data
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("FILE", new FileSystemResource(file));
map.add("APPLICATION_ID", Number);
httpService.post( map,headers);
At receiver end use
#RequestMapping(value = "fileUpload", method = RequestMethod.POST)
public ApiResponse AreaCsv(#RequestParam("FILE") MultipartFile file,#RequestHeader("clientId") ){
//code
}
Using HttpRequestFactory to jira xray's /rest/raven/1.0/import/execution/cucumber/multipart :
Map<String, Object> params = new HashMap<>();
params.put( "info", "zigouzi" );
params.put( "result", "baalo" );
HttpContent content = new UrlEncodedContent(params);
OAuthParameters oAuthParameters = jiraOAuthFactory.getParametersForRequest(ACCESS_TOKEN, CONSUMER_KEY, PRIVATE_KEY);
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(oAuthParameters);
HttpRequest request = requestFactory.buildPostRequest(new GenericUrl(url), content);
request.getHeaders().setAccept("application/json");
String boundary = Long.toHexString(System.currentTimeMillis());
request.getHeaders().setContentType("multipart/form-data; boundary="+boundary);
request.getHeaders().setContentEncoding("application/json");
HttpResponse response = null ;
try
{
response = request.execute();
Scanner s = new Scanner(response.getContent()).useDelimiter("\\A");
result = s.hasNext() ? s.next() : "";
}
catch (Exception e)
{
}
did the trick.

SpringMVC-FileUpload - The request sent by the client was syntactically incorrect

I've seen couple of qts on the same topic. But I didn't find any clue of this error.
I am working on a POC and following the link below.
http://spring.io/guides/gs/uploading-files/
As mentioned in the above tutorial, in standalone mode[spring embeded Tomcat] it is working absolutely fine.
But I want to deploy it as webapplication. So, I have created a separate SpringMVC project and added the following controller.
Controller file
#Controller
public class FileUploadController {
#RequestMapping(value="/upload", method=RequestMethod.GET)
public #ResponseBody String provideUploadInfo() {
return "You can upload a file by posting to this same URL.";
}
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file){
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name + "-uploaded")));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + name + " into " + name + "-uploaded !";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name + " because the file was empty.";
}
}
}
I've written the following client ( As I don't want to use RestTemplate here).
Service Client
private static final String URL_GET = "http://localhost:8080/SpringMVC/upload";
static String URL = "http://localhost:8080/SpringMVC/upload";
public static void main(String[] args) throws Exception {
PropertyConfigurator.configure("C:/DevEnvProject/eclipse/workspace_exp/OCR/log4j.properties");
testGet();
testPOST();
}
private static void testGet() throws ClientProtocolException, IOException {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet(URL_GET);
HttpResponse response = httpClient.execute(httpGet, localContext);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse = reader.readLine();
}
static void testPOST() {
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(URL);
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("name", new StringBody("testIcon.png"));
entity.addPart("file", new FileBody(new File("C:/testIcon.png")));
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost, localContext);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse = reader.readLine();
} catch (Exception e) {
e.printStackTrace();
}
}
I couldn't make a successful call to the POST endpoint. Everytime, I'm getting the following exception.
400 Bad Request - The request sent by the client was syntactically incorrect
'GET' call is working fine. I compared the the log of the 'POST' request with the same 'POST' request which I got while testing with standalone approach as mentioned in the spring tutorial. Didn't find any diff in the request part.
I know that I'm quite verbose in this post. I wanted to give as much context info as possible. Please help.
Thanks
There are 2 things you need to do:
First, add the Apache Commons FileUpload library to your class path. If you use maven, you can get the dependency here. If you don't, you can still download the jar and add it manually.
Second, you have to declare a MultipartResolver bean in your context with name multipartResolver. With Apache Commonds FileUpload, you can use CommonsMultipartResolver. For example, with Java config, that would be
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
// set any fields
return commonsMultipartResolver;
}
With XML config,
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- set any properties -->
</bean>
This is further documented in the Spring official documentation.

apache HttpClient, upload a file via form: use StringBody instead of FileBody

A web server expects a file to be uploaded via an html form.
This is the way how i construct the MultipartEntity, that already works:
FileBody filePart = new FileBody(new File("emptyFile.txt"), "text/plain");
FormBodyPart fbp = new FormBodyPart("UploadService", filePart);
MultipartEntity mpe = new MultipartEntity();
mpe.addPart(fbp);
The fact is that i have my data in memory, so i don't like the idea of saving it to disk, and so I've tried to replace
FileBody filePart = new FileBody(new File("emptyFile.txt"), "text/plain");
with
StringBody filePart = new StringBody("");
But the second way doesn't work, the server returns a HTTP 500 exception; logging the data on the wire, i noticed that the only difference is as follows:
HTTP POST trace when FileBody has been used:
...
Content-Disposition: form-data; name="UploadService"; filename="emptyFile.txt"
...
HTTP POST trace when StringBody has been used:
...
Content-Disposition: form-data; name="UploadService"
...
That is, in the FileBody upload, it is specified a "filename" that is not specified in the StringBody upload.
How can i fix this?
With a StringBody you won't be able to set a filename. But you can extend StringBody and override getFilename() to not return null.
According to the sources for FormBodyPart, this should be enough to have the desired filename-parm parameter:
protected void generateContentDisp(final ContentBody body) {
StringBuilder buffer = new StringBuilder();
buffer.append("form-data; name=\"");
buffer.append(getName());
buffer.append("\"");
if (body.getFilename() != null) {
buffer.append("; filename=\"");
buffer.append(body.getFilename());
buffer.append("\"");
}
addField(MIME.CONTENT_DISPOSITION, buffer.toString());
}
Just dropping this here, as I had the issue and kept coming here in my searches... Similar to the approach above, but I guess it is simpler.
public class StringFileBody extends FileBody {
private String data;
public StringFileBody( String input, ContentType contentType ) {
super( new File( "." ), contentType );
data = input;
}
public StringFileBody( String input, ContentType contentType, String fileName ) {
super( new File( "." ), contentType, fileName );
data = input;
}
#Override
public void writeTo( OutputStream out ) throws IOException {
out.write( data.getBytes( ) );
}
#Override
public long getContentLength( ) {
return data.getBytes( ).length;
}
}

Categories