1

I am developing an Android applicaiton with AppEngine backend. I am creating the server part with Google Cloud Endpoints in Java. My problem is that I cannot send a Bitmap from the client to the server.

I used the answer from this question but even if the client part does not seem to have any problems at all, the server part does not receive the data at all. I also think this solution might be a bit complicated and that it might work a different, easier way, however this is my first time implementing a server and first time sending a picture to it so I accept any good tips on this. Thanks!

Here is my code:

        String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
        String CRLF = "\r\n"; // Line separator required by multipart/form-data.
        String charset = "UTF-8";

        HttpURLConnection connection = (HttpURLConnection) new URL("https://path_to_my_app/_ah/api/registration/v1/uploadImage").openConnection();
        connection.setDoOutput(true);
        connection.setReadTimeout(60000);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        PrintWriter writer = null;
        try {
            OutputStream output = connection.getOutputStream();
            writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!

            // Send text file.
            writer.append("--" + boundary).append(CRLF);
            writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + somename + "\"").append(CRLF);
            writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
            writer.append(CRLF).flush();
            BufferedReader reader = null;

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            photo.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
            byteArray = stream.toByteArray();

            try {
                reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(byteArray), charset));
                for (String line; (line = reader.readLine()) != null;) {
                    writer.append(line).append(CRLF);
                }
            } finally {
                if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
            }
            writer.flush();


//            End of multipart/form-data.
        writer.append("--" + boundary + "--").append(CRLF);
    }
    finally
    {
        if (writer != null)
        {
            writer.close();
        }
    }

The server part:

@ApiMethod(name = "uploadImage", httpMethod = "POST")
public void uploadImage(HttpServletRequest request, HttpServletResponse response) throws IOException
{
    ServletFileUpload fileUpload = new ServletFileUpload();
    try
    {
        FileItemIterator iterator = fileUpload.getItemIterator(request);

        while(iterator.hasNext()){
            FileItemStream itemStream = iterator.next();

            String fieldName = itemStream.getFieldName();
            log.info("field name:"+fieldName);

            InputStream stream = itemStream.openStream();

            String result = getStringFromInputStream(stream);
            log.info("result: "+result);

            stream.close();
        }
    }
    catch (FileUploadException e)
    {
        e.printStackTrace();
    }

}

I am getting 204 no Content type now.

Community
  • 1
  • 1
vandus
  • 3,248
  • 3
  • 30
  • 44
  • Convert image into base64 string and store it on server. it will work. – user3607917 Aug 14 '14 at 14:06
  • Look at the example you gave. The Content-Type cannot be 'text/plain' for an image which is a binary file. – greenapps Aug 14 '14 at 14:26
  • what should I put there then? I tried multipart/form data. I guess the problem might also be in the server method argument data type – vandus Aug 14 '14 at 14:33
  • So I changed it to the multipart content type and I have updated the my question on the very bottom. I just dont know how to get the image on the server side now. – vandus Aug 14 '14 at 14:53

1 Answers1

3

I did it!

I think this is not the best way of doing it but it´s working so I am fine until I get a better solution.

So I take the Bitmap image and convert it to String:

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byte[] bitmapByte = outputStream.toByteArray();
String stringEncodedImage = Base64.encodeToString(bitmapByte, Base64.DEFAULT);

Then I create a httpPostRequest and set a JsonObject to it with the image converted to String in it.

HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://my_app_path/_ah/api/registration/v1/uploadImage");

JSONObject jsonObject = new JSONObject();
jsonObject.put("image",stringEncodedImage);

StringEntity stringEntity = new StringEntity(jsonObject.toString());
httpPost.addHeader("Content-Type", "application/json");
httpPost.setEntity(stringEntity);
HttpResponse response = httpClient.execute(httpPost);

On the server side, in my Endpoint, I do this:

@ApiMethod(name = "uploadImage", httpMethod = "POST")
public JSONObject uploadImage(JSONObject request) throws IOException
{
    String imageInString = (String) request.get("image");
    Blob blob = new Blob(imageInString.getBytes());
    ....save blob and do whatever you want...
}

The same goes the other way. I pack Blob into JsonObject and send it over.

vandus
  • 3,248
  • 3
  • 30
  • 44