I'm using the library QRCodeWriter that create a QR and send it to an API.
The issue is that I have variable os where the image is stored, but I can not able to add it to MultipartEntity to send it (commented line).
The error is: incompatible types: ByteArrayOutputStream cannot be converted to ContentBody entity.addPart("file", os)
I tried a lot of code to convert the image without success.
Any help will be apreciated
String url = "https://apiURL.com";
String accessToken = "123456789";
QRCodeWriter writer = new QRCodeWriter();
BitMatrix matrix = writer.encode("https://www.google.com/", BarcodeFormat.QR_CODE, 350, 350);
BufferedImage image = MatrixToImageWriter.toBufferedImage(matrix);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.setUseCache(false);
ImageIO.write(image,"png",os);
context.log(os.toString());
basicIO.write("TestData");
MultipartEntity entity = new MultipartEntity();
//entity.addPart("file", os);
HttpResponse returnResponse = Request.Post(url).addHeader("Authorization", accessToken).body(entity).execute().returnResponse();
context.log("Response status: " + returnResponse.getStatusLine().getStatusCode());
context.log(EntityUtils.toString(returnResponse.getEntity()));
It works changing:
entity.addPart("file", os);
to:
entity.addPart("file", new ByteArrayBody(os.toByteArray(), "qr.png"));
I have an Android device. I want to fill a form in my app, with edittexts etc (one of these fields would take the path of an image on the SDCard). I want these form contents to be the data for an HTML form in an external website where this file (from the SD Card) needs to be uploaded. The HTML form has an upload button. I do not want to show this HTML webpage to my android app users. Is there any way to do this? Please let me know! Thanks!
EDIT: I've looked through many websites and I understand that I should use a HttpPost. I have a few doubts though:
1. What is the url that you use in HttpPost- Is it the url which contains the form, or the url which the form redirects to.
2. In a multipartentity, what is the first parameter in addPart? Is it the ID given to the field or the name?
3. How does the HttpPost know which form it should go to?
Well, you need to make a MultiPart Http Post. You could use this sample:
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("target_link");
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("data1", new StringBody("Data1"));
reqEntity.addPart("data2", new StringBody("Data2"));
reqEntity.addPart("data3",new StringBody("Data3"));
try{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 80, bos);
byte[] data = bos.toByteArray();
ByteArrayBody bab = new ByteArrayBody(data, "forest.jpg");
reqEntity.addPart("picture", bab);
}
catch(Exception e){
//Log.v("Exception in Image", ""+e);
reqEntity.addPart("picture", new StringBody(""));
}
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
Personally, I prefer to use Spring for Android as that is easier to configure. Here's a link with a multi-part Http Post.
Good luck!
The whole thing works perfectly, except image won't show, no errors, Using RoR. What am I missing? All called by async class btw. Been trying several different methods with no avail, if someone could help me out that would be great. Willing to post more if needed.
Thanks!
public static void multiPart(Bitmap image, String topicid, String topost, Context c){
String responseString = "";
{
try {
String imageName = System.currentTimeMillis() + ".jpg";
HttpClient httpClient = new MyHttpClient(c);
HttpPost postRequest = new HttpPost("https://urlofmyapi");
if (image==null){
Log.d("TAG", "NULL IMAGE");
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
image.compress(CompressFormat.JPEG, 75, bos);
byte[] data = bos.toByteArray();
ByteArrayBody bab = new ByteArrayBody(data, imageName);
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("feed", new StringBody(topost));
reqEntity.addPart("post_to", new StringBody(topicid));
reqEntity.addPart("upload_file", bab);
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader reader = new BufferedReader(
new InputStreamReader(
response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
responseString = s.toString();
System.out.println("Response: " + responseString);
} catch (Exception e) {
Log.e(e.getClass().getName(), 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
HTTP POSTing images from Java to RoR always seems to have undue issues for me. Have you tried attaching the binary as a org.apache.http.entity.mime.content.FileBody object, like this Android Multipart Upload question?
I need help in using, imgur's API, to upload a photo and obviously retrieve a link.
IMGUR API:
http://api.imgur.com/resources_anon
I'm able to get the URI for my image required to be uploaded but how can I implement the api above,
I've downloaded mime4j and httpmime and added them to the libraries, but I can't seem to understand how to use them,
I looked at this but its confused me :
Sending images using Http Post
Just from having a quick look at imgur and this question, I've come up with (pretty much just combined the two) the following. Let me know if it doesn't work.
Bitmap bitmap = yourBitmapHere;
// Creates Byte Array from picture
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); // Not sure whether this should be jpeg or png, try both and see which works best
URL url = new URL("http://api.imgur.com/2/upload");
//encodes picture with Base64 and inserts api key
String data = URLEncoder.encode("image", "UTF-8") + "=" + URLEncoder.encode(Base64.encode(baos.toByteArray(), Base64.DEFAULT).toString(), "UTF-8");
data += "&" + URLEncoder.encode("key", "UTF-8") + "=" + URLEncoder.encode(YOUR_API_KEY, "UTF-8");
// opens connection and sends data
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
Edit: It seems we need to pass Base64.DEFAULT as the second option to Base64.encode. Updated the example above.
Edit 2: Can you use the following code, based upon the oracle site, and report back what it outputs:
BufferedReader in = new BufferedReader(
new InputStreamReader(
conn.getInputStream()));
String inputLine;
while ((inputLine = ic.readLine()) != null)
System.out.println(inputLine);
in.close();
For my current application I collect images from different "event
providers" in Spain.
Bitmap bmp=null;
HttpGet httpRequest = new HttpGet(strURL);
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
Log.i(TAG, "Image ["+ strURL + "] fetched in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
InputStream instream = entity.getContent();
bmp = BitmapFactory.decodeStream(instream);
return bmp;
However, when downloading images from salir.com I get the following
logcat output:
13970 Gallery_Activity I Fetching image 2/8 URL: http://media.salir.com/_images_/verticales/a/0/1/0/2540-los_inmortales_la_trattoria-marc_aureli_27_29_no.jpg
13970 ServiceHttpRequest I Image [http://media.salir.com/_images_/verticales/a/0/1/0/2540-los_inmortales_la_trattoria-marc_aureli_27_29_no.jpg] fetched in [146ms]
13970 skia D --- decoder->decode returned false
A search for that error message didn't provide much useful results.
Anyone an idea what the problem could be?
Gracias!
Update 1:
After inquiring a bit more and testing different stuff I figured out that the problem seems to lie somewhere else. Even though my logcat output says
13970 ServiceHttpRequest I Image [http://media.salir.com/_images_/verticales/a/0/1/0/2540-los_inmortales_la_trattoria-marc_aureli_27_29_no.jpg] fetched in [146ms]
getContentLength(): 93288
which is the correct length of the image in bytes it seems that there's something wrong with the stream or HTTP connection.
My original code (above) is taking advantage of the ThreadSafeClientConnManager. If I replace it with just a simple URLConnection it works perfectly:
URL url = new URL(strURL);
URLConnection conn = url.openConnection();
conn.connect();
InputStream instream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(instream);
So, I'm wondering now why does my ThreadSafeClientConnManager work flawlessly (at least it seems it does) with all my other connections (mostly exchanging JSONObjects) but not with images from some specific websites (e.g. salir.com - for most other websites it works, though). Is there a HTTP parameter I'm missing?
My current setup is:
HttpParams parameters = new BasicHttpParams();
HttpProtocolParams.setVersion(parameters, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(parameters, HTTP.UTF_8);
HttpProtocolParams.setUseExpectContinue(parameters, false); // some webservers have problems if this is set to true
ConnManagerParams.setMaxTotalConnections(parameters, MAX_TOTAL_CONNECTIONS);
HttpConnectionParams.setConnectionTimeout(parameters, CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(parameters, SOCKET_TIMEOUT);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http",
PlainSocketFactory.getSocketFactory(), HTTP_PORT));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(parameters,schReg);
DefaultHttpClient http_client = new DefaultHttpClient(conMgr, parameters);
Update 2:
Now, the strange thing is, that it actually does work with the ThreadSafeClientConnManager -sometimes-. If I keep trying downloading the image and decoding it for a couple of times in a row it might work after 15-30 trials. Very strange.
I hope there's a solution to that since I would prefer using the ThreadSafeClientConnManager instead of URLConnection.
Update 3:
As suggest by Mike Mosher below, it seems that by using BufferedHttpEntity the decoding error doesn't appear any more. However now, even though less often than before, I get a SkImageDecoder::Factory returned null error.
Stefan,
I've had the same issue, and didn't find much searching the internet. Many people have had this issue, but not alot of answers to solve it.
I was fetching images using URLConnection, but I found out the issue doesn't lie in the download, but the BitmapFactory.decodeStream was having an issue decoding the image.
I changed my code to reflect your original code (using httpRequest). I made one change, which I found at http://groups.google.com/group/android-developers/browse_thread/thread/171b8bf35dbbed96/c3ec5f45436ceec8?lnk=raot (thanks Nilesh). You need to add "BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity); "
Here was my previous code:
conn = (HttpURLConnection) bitmapUrl.openConnection();
conn.connect();
is = conn.getInputStream();
//bis = new BufferedInputStream(is);
//bm = BitmapFactory.decodeStream(bis);
bm = BitmapFactory.decodeStream(is);
And her is the code that works:
HttpGet httpRequest = null;
try {
httpRequest = new HttpGet(bitmapUrl.toURI());
} catch (URISyntaxException e) {
e.printStackTrace();
}
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream instream = bufHttpEntity.getContent();
bm = BitmapFactory.decodeStream(instream);
As I said, I have a page that download around 40 images, and you can refresh to see the most recent photos. I would have almost half fail with the "decoder->decode returned false error". With the above code, I have had no problems.
Thanks
My solution is not to use BitmapFactory.decodeStream() cause the way I look at it, it uses the SKIA decoder and it seems kind of erratic sometimes. You can try something like this.
Bitmap bitmap = null;
InputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new URL(url).openStream(),
IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
} catch (......){
}
and for the copy() function
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
}
and IO_BUFFER_SIZE is a constant integer with the value of 4 * 1024.
This is a Android bug. Your code is ok.
"Android's decoders do not currently support partial data on decode."
If you got image in entity probably it's a partial input stream, and android can't cope with that at the moment.
Solution is to use FlushedInputStream from this thread:
http://code.google.com/p/android/issues/detail?id=6066
Also try adding this option.
opt.inPurgeable = true;
HttpGet httpRequest = null;
try {
httpRequest = new HttpGet(url);
} catch (Exception e) {
e.printStackTrace();
}
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream instream = bufHttpEntity.getContent();
Bitmap bm = BitmapFactory.decodeStream(instream);
I was having a similar problem, and the root issue was due to timeouts when requesting some images. I switched to using a Background Image Loader and have had no problems since. Hope this helps
I've tried tree diffrent ways now, the simple URLConnection you use and that seems to be working for you, the way Mike Mosher uses and also this way [http://asantoso.wordpress.com/2008/03/07/download-and-view-image-from-the-web/] they all result in decode returned false.
HOWEVER if I convert the image to a PNG all of the ways work fine!! However I tried putting the images on my work ftp homepage and then all jpgs load fine with the simple solution... So for some reason it seems that if the server isn't fast enough it parses the jpg files before they are actually fully downloaded or something.
I had the exact same problem when trying to decode an image from a byte array. After some experimentation, the solution appears to be to assign some temp storage in the Options of the BitmapFactory. Try:
Options options = new Options();
options.inTempStorage = new byte[256];
Bitmap newMapBitmap = BitmapFactory.decodeStream(instream, null, options);
If the problem is not resolved straight away, try increasing the size of the temp array. I think large bitmap files need a larger buffer for decoding.
Setting the default buffer in Options does help with some out of memory issues regarding BitmapFactory but certainly does not cover all of them. The underlying issue appears to be some kind of timeout when retrieving the bitmap or the bitmap header. I am now writing the stream to a temp file and then pass the temp file to BitmapFactory which is working fine.
I experience this error “SkImageDecoder::Factory returned null” about 1 out of 8 times, even if I download the entire file to a buffer, then decode the byte array to a bitmap. I tried the following and none worked for me:
Using only URLs, not http connection types
Buffered readers
Download entire file, then do decode
I don’t believe the flushed input stream workaround would work either.
It does appear to be an Android skia bug. People are still reporting problems here:
http://code.google.com/p/android/issues/detail?id=6066.
I have no workaround for this bug except to retry if the bitmap is null, which only reduces the chances of getting the error.
HttpURLConnection hConn = null;
hConn = openHttpConnection(szUrl);
hConn.setRequestMethod("GET");
hConn.setRequestProperty("User-Agent",szUserAgent);
hConn.setRequestProperty("Accept",szAccept);
hConn.setRequestProperty("Accept-Charset",szCharset);
hConn.setInstanceFollowRedirects(true);
hConn.setUseCaches(true);
hConn.setChunkedStreamingMode(8*1024);
hConn.setDoInput(true);
hConn.setConnectTimeout(60*1000);
hConn.setReadTimeout(60*1000);
hConn.connect();
InputStream bmpIs = hConn.getInputStream();
BufferedInputStream bmpBis = new BufferedInputStream(bmpIs);
Bitmap bmpThumb = null;
BitmapFactory.Options bfOpt = new BitmapFactory.Options();
bfOpt.inScaled = true;
bfOpt.inSampleSize = 2;
bfOpt.inPurgeable = true;
bmpThumb = BitmapFactory.decodeStream(bmpBis,null,bfOpt);
if(bmpThumb == null)
{
for(int i=0; i<10; i++)
{
Thread.sleep(200);
System.gc();
bmpThumb = BitmapFactory.decodeStream(bmpBis,null,bfOpt);
if(bmpThumb == null)
bfOpt.inSampleSize += 1;
else
break;
}
}