Send Unicode characters via MultipartEntity - android

I have a method to send image and text as a HttpPost using MultipartEntity content type. Everything works great with English symbols, but for unicode symbols (for example Cyrliics) it sends only ???. So, I'm wondering, how to set UTF-8 encoding for MultipartEntity correctly, since I've tried several sulutions, suggested on SO, but none of them worked.
Here what I have already:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
MultipartEntityBuilder mpEntity = MultipartEntityBuilder.create();
mpEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
mpEntity.setCharset(Consts.UTF_8);
mpEntity.addPart("image", new FileBody(new File(attachmentUri), ContentType.APPLICATION_OCTET_STREAM));
ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);
StringBody stringBody = new StringBody(mMessage, contentType);
mpEntity.addPart("message", stringBody);
final HttpEntity fileBody = mpEntity.build();
httpPost.setEntity(fileBody);
HttpResponse httpResponse = httpclient.execute(httpPost);
UPD
I tried to use InputStream as per #Donaudampfschifffreizeitfahrt suggestion. Now I'm getting ��� characters.
InputStream stream = new ByteArrayInputStream(mMessage.getBytes(Charset.forName("UTF-8")));
mpEntity.addBinaryBody("message", stream);
Also tried:
mpEntity.addBinaryBody("message", mMessage.getBytes(Charset.forName("UTF-8")));

I solved it a different way, using:
builder.addTextBody(key, שלום, ContentType.TEXT_PLAIN.withCharset("UTF-8"));

You can use below line for add part in multipart entity
entity.addPart("Data", new StringBody(data,Charset.forName("UTF-8")));
to send unicode in request.

To the ones who stuck with this issue, this is how I resolved it:
I investigated apache http components libraries source code and found following:
org.apache.http.entity.mime.HttpMultipart::doWriteTo()
case BROWSER_COMPATIBLE:
// Only write Content-Disposition
// Use content charset
final MinimalField cd = part.getHeader().getField(MIME.CONTENT_DISPOSITION);
writeField(cd, this.charset, out);
final String filename = part.getBody().getFilename();
if (filename != null) {
final MinimalField ct = part.getHeader().getField(MIME.CONTENT_TYPE);
writeField(ct, this.charset, out);
}
break;
So, seems like it is some kind of bug / feature in apache lib, which only allowes to add Content-type header to one part of MultipartEntity, if this part has filename not null. So I modified my code as:
Charset utf8 = Charset.forName("utf-8");
ContentType contentType = ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), utf8);
ContentBody body = new ByteArrayBody(mMessage.getBytes(), contentType, "filename");
mpEntity.addPart("message", body);
And Content-type header appeared for string part, and symbols are now encoded and decoded correctly.

Related

Parts of post data lost when using org.apache.http library

I'm having some issues with incomplete post data being received by our server. This only occurs for a few users of our app. Still not sure which versions of Android we are talking about, but will try to recover that information as soon as possible.
For the time being: maybe there is someone who also experienced similar problems? It occurs only for our textarea field where users can type large custom texts. There is no filter whatsoever on this field, and will be sent as StringBody to our server directly. The code below is the relevant parts. My concern is the part where the StringBody is created. Is this sufficient for escaping the text properly to not interfere with the post headers?
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
for(int j=0; j<fields.length; j++){
String value = mydata.get(fields[j]);
entity.addPart(fields[j], new StringBody(value, "text/plain", Charset.forName("UTF-8")));
}
(..) //some files are added too later on
entity.addPart(image.get("hash"), new FileBody(imageFile));
(..) //and sending the data to the server
HttpPost post = new HttpPost(url);
if(entity != null)
post.setEntity(entity);
final HttpClient http = new DefaultHttpClient();
final HttpParams params = http.getParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 30000);
ConnManagerParams.setTimeout(params, 30000);
HttpResponse response = http.execute(post);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() != HttpStatus.SC_OK){
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
String result = out.toString();
Finally solved this problem. The problem was not in the frontend but in the backend. People were posting unicode emoticons . The backend was built with an MySQL utf8_general_ci collation table/column. This collation does not support the unicode characters and will break the text before the unicode character. So the resulting insert will have all text missing after the unicode character.

Android - send data to server with HttpURLConnection

I was following this tutorial to upload images with android: here
After the line conn.setRequestProperty("uploaded_file", fileName); in function uploadFile(String sourceFileUri) I added further lines with conn.setRequestProperty("title", "example"); conn.setRequestProperty("name", "simple_image"); but in the php file I am not receiving these strings with $_POST or $_GET only the image is uploaded.
Is this tutorial here only for uploading images?
I would like to send with the image some other data too. How could I do this?
Thank you
Yes that tutorial is for uploading a single file only.If you want to send some other data(may be some strings) along with your image, then you can use MultipartEntityBuilder.However to use this you need to download the jars from the Apache HttpComponents site and add them to project and path(just add the httpclient jar to your libs folder).
Now for uploading an image along with some string data you can use (may be inside doInBackground of your AsynTask)
File file = new File("yourImagePath");
String urlString = "http://yoursite.com";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(urlString);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
/* setting a HttpMultipartMode */
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
/* adding an image part */
FileBody bin1 = new FileBody(file);
builder.addPart("uploadedfile1", bin1);
builder.addPart("user", new StringBody("Some String",ContentType.TEXT_PLAIN));//adding a string
HttpEntity reqEntity = builder.build();
post.setEntity(reqEntity);
HttpEntity resultEntity = httpResponse.getEntity();
String result = EntityUtils.toString(resultEntity);
P.S : I assumed you are using AsyncTask for uploading process and that's the reason i said to use this code inside doInBackground of your AsyncTask.
You can use MultipartEntity too.Follow this tutorial which describes how to upload multiple images along with some other string data using MultipartEntity.However there's not much difference in the implementation of MultipartEntity and MultipartEntityBuilder.Try yourself to learn both.Hope these info help you.

Uploading file via form into GAE from Android

I have an app on GAE at: http://1.myawesomecity.appspot.com/
FIXED:
HttpPost post = new HttpPost("http://1.myawesomecity.appspot.com/");
http_client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
String result = EntityUtils.toString( http_client.execute(post).getEntity(), "UTF-8");
String actualURL = result.substring(result.indexOf("http://"), result.indexOf("\" method"));
Log.w("asdf", "url " + actualURL );
post = new HttpPost(actualURL);
http_client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
String mime_type = "image/png";
File file = new File( filename ); //context.getFilesDir(),
entity.addPart( "myFile", new FileBody( file, mime_type));
post.setEntity( entity );
String res = EntityUtils.toString( http_client.execute(post).getEntity(), "UTF-8");
Log.w("asdf", res);
The above grabs the ACTUAL upload URL from the GAE server, and passes in the file as dictated by the CORRECT answer below.
Old Question:
As you can see, if you choose a file and hit submit, it will 404, but the file actually does get stored (as long as it is not too big, < 100kb). Don't type in anything in the first text field.
Now, putting aside how this particular app is barely functional, I'm trying to upload a file from Android onto this server.
The site's upload script uses blobstore, and the file field's name is "myFile".
Now in my Android app, I have:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(<my app's url>);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("myFile", <path to a file selected by user> ) );
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httpclient.execute(httppost);
This throws an exception.
How is this any different from me going to my site through a browser, choosing a file, and hitting submit? Why does going through a browser actually go through with uploading the file, when the Android code does not?
I know that my filepath is valid. Is there something I'm doing wrong? or is clicking on "submit" from a browser different from executing a httpclient from Android?
Uploading file to a blobstore on GAE is a two step process:
first you need to get a proper URL where to POST your data, usually people use something like "/bloburl" handler for that purpose
when you have blob upload URL, you use it in your request.
the file you send does not go as NameValuePair, it's supposed to go as a MultiPartEntity.
here's the code that works (you'll need apache http library for MultiPartEntry support):
DefaultHttpClient http_client = new DefaultHttpClient();
HttpGet http_get = new HttpGet(Config.BASE_URL + "bloburl");
HttpResponse response = http_client.execute(http_get);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String first_line = reader.readLine();
Log.w(TAG, "blob_url: " + first_line);
HttpPost post = new HttpPost(first_line);
http_client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
mime_type = "application/zip";
File file = new File( context.getFilesDir(), filename );
entity.addPart( "file", new FileBody( file, mime_type));
post.setEntity( entity );
String result = EntityUtils.toString( http_client.execute(post).getEntity(), "UTF-8");
Log.i(TAG, result);

Android - Upload Large image to server

I am trying to have my application upload images to the webserver using the code below. It works sometimes, but also seems to fail with a memory error. Can someone please post an example of how to accomplish this if the file size is to big? Also, I am building this to support 1.5 and up. I don't mind if the code given to me resizes the image smaller before upload.
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(urlString);
File file = new File(nameOfFile);
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamEntity reqEntity = new InputStreamEntity(fileInputStream, file.length());
httppost.setEntity(reqEntity);
reqEntity.setContentType("binary/octet-stream");
HttpResponse response = httpclient.execute(httppost);
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
responseEntity.consumeContent();
}
httpclient.getConnectionManager().shutdown();
You have two option to make your code workable.
You should use multi part approach to upload larger size file. Which i am using in my code.
Its Apache code. (Yes, you can easily port it in your Android project).
You can minimize the image resolution. by using SampleSize flag,
Follow this link.
I hope it help.
You can try following code for uploading images.
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
MultipartEntity multiPart = new MultipartEntity();
multiPart.addPart("my_picture", new FileBody(new File(IMG_URL)));
httpPost.setEntity(multiPart);
HttpResponse res = httpClient.execute(httpPost);
you should really look into setChunkedStreamingMode of the connection. or, indeed, use MultipartEntity (it's apache httpcomponents library - you will easily find lots of solutions on this.
as for resizing images, it's quite simple:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; // look at the link Rajnikant gave for more details on this
Bitmap bitmap = BitmapFactory.decodeFile(filename, options);
// here you save your bitmap to whatever you want
but it is memory consuming too...

Android Multipart Upload

As part of my Android app, I'd like to upload bitmaps to be remotely stored. I have simple HTTP GET and POST communication working perfectly, but documentation on how to do a multipart POST seems to be as rare as unicorns.
Furthermore, I'd like to transmit the image directly from memory, instead of working with a file. In the example code below, I'm getting a byte array from a file to be used later on with HttpClient and MultipartEntity.
File input = new File("climb.jpg");
byte[] data = new byte[(int)input.length()];
FileInputStream fis = new FileInputStream(input);
fis.read(data);
ByteArrayPartSource baps = new ByteArrayPartSource(input.getName(), data);
This all seems fairly clear to me, except that I can't for the life of me find out where to get this ByteArrayPartSource. I have linked to the httpclient and httpmime JAR files, but no dice. I hear that the package structure changed drastically between HttpClient 3.x and 4.x.
Is anyone using this ByteArrayPartSource in Android, and how did they import it?
After digging around in the documentation and scouring the Internet, I came up with something that fit my needs. To make a multipart request such as a form POST, the following code did the trick for me:
File input = new File("climb.jpg");
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://localhost:3000/routes");
MultipartEntity multi = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
String line;
multi.addPart("name", new StringBody("test"));
multi.addPart("grade", new StringBody("test"));
multi.addPart("quality", new StringBody("test"));
multi.addPart("latitude", new StringBody("40.74"));
multi.addPart("longitude", new StringBody("40.74"));
multi.addPart("photo", new FileBody(input));
post.setEntity(multi);
HttpResponse resp = client.execute(post);
The HTTPMultipartMode.BROWSER_COMPATIBLE bit is very important. Thanks to Radomir's blog on this one.
try this:
HttpClient httpClient = new DefaultHttpClient() ;
HttpPost httpPost = new HttpPost("http://example.com");
MultipartEntity entity = new MultipartEntity();
entity.addPart("file", new FileBody(file));
httpPost.setEntity(entity );
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (ClientProtocolException e) {
Log.e("ClientProtocolException : "+e, e.getMessage());
} catch (IOException e) {
Log.e("IOException : "+e, e.getMessage());
}
Perhaps you can do following step to import library into your Android.
requirement library
- apache-mime4j-0.6.jar
- httpmime-4.0.1.jar
Right click your project and click properties
select java build path
select tab called "Order and Export"
Apply it
Fully uninstall you apk file with the adb uninstall due to existing apk not cater for new library
install again your apk
run it
Thanks,
Jenz
I'm having the same problem. I'm trying to upload an image through MultiPart Entity and it seens that the several updates on HttpClient/MIME are cracking everything. I'm trying the following code, falling with an Error "NoClassDefFoundError":
public static void executeMultipartPost(File image, ArrayList<Cookie> cookies, String myUrlToPost) {
try {
// my post instance
HttpPost httppost = new HttpPost(myUrlToPost);
// setting cookies for the connection session
if (cookies != null && cookies.size() > 0) {
String cookieString = "";
for (int i=0; i<cookies.size(); ++i) {
cookieString += cookies.get(i).getName()+"="+cookies.get(i).getValue()+";";
}
cookieString += "domain=" + BaseUrl + "; " + "path=/";
httppost.addHeader("Cookie", cookieString);
}
// creating the http client
HttpClient httpclient = new DefaultHttpClient();
// creating the multientity part [ERROR OCCURS IN THIS BELLOW LINE]
MultipartEntity multipartEntity = new MultipartEntity();
multipartEntity.addPart("photoupload", new FileBody(image));
httppost.setEntity(multipartEntity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
} catch (Exception e) {}
}
This method is fully compilable and uses the httpclient-4.0.1.jar and httpmime-4.2.jar libs, but again, I remember that it crashs in the commented line for me.

Categories

Resources