通过httpPost上传base64映像到服务器的问题

问题描述:

我正在使用JSON和HttpPost将本地SQLite数据库的全部内容发送到远程MySQL数据库的应用程序原型。通过httpPost上传base64映像到服务器的问题

一切工作正常的文本数据。 现在我向派对中添加了图像,但我可以将图像作为base64字符串添加到我发送的JSON中。我的图像是800 x 600像素,每个大小或多或少500kb。

如果我手动将我的应用程序生成的JSON粘贴到网页上,那很好,我得到了我的图像和其他一切。

使用的应用程序上传脚本,我尝试上传的JSON字符串4张图片,但应用程序卡住我的进度对话框和logcat的推移遍地显示这一点:

11-15 14:32:27.809: I/dalvikvm-heap(15562): Grow heap (frag case) to 21.964MB for 2680048-byte allocation 
11-15 14:32:27.840: D/dalvikvm(15562): GC_CONCURRENT freed 1744K, 30% free 20666K/29447K, paused 2ms+3ms 
11-15 14:32:27.879: D/dalvikvm(15562): GC_FOR_ALLOC freed 4362K, 39% free 18049K/29447K, paused 16ms 
11-15 14:32:27.918: D/dalvikvm(15562): GC_FOR_ALLOC freed 0K, 33% free 19794K/29447K, paused 22ms 
11-15 14:32:27.918: I/dalvikvm-heap(15562): Grow heap (frag case) to 21.964MB for 2680276-byte allocation 
11-15 14:32:27.958: D/dalvikvm(15562): GC_CONCURRENT freed 1744K, 30% free 20667K/29447K, paused 1ms+4ms 
11-15 14:32:27.997: D/dalvikvm(15562): GC_FOR_ALLOC freed 4362K, 39% free 18049K/29447K, paused 17ms 
11-15 14:32:28.028: D/dalvikvm(15562): GC_FOR_ALLOC freed 0K, 33% free 19795K/29447K, paused 17ms 

,并继续永远。我敢打赌,这些图像太大了,无法用这种方式发送,或者我在某个地方泄漏了内存。

将大尺寸图像和JSON数据一起上传到服务器会更好吗?否则,我该如何避免内存泄漏?

的代码是非常标准...

从光标到JSON:

private JSONObject get_images_data_JSON(Cursor c) { 

    JSONObject image_jo = new JSONObject(); 

    //get unit identifier 
    long unit_identifier = c.getLong(c.getColumnIndex("_id")); 

    //set unit details 
    try { 

     image_jo.put("_id", unit_identifier); 
     image_jo.put("unit_id", c.getLong(c.getColumnIndex("unit_id"))); 

     //encode blob in Base64 for json parsing 
     String encodedImage = Base64.encodeToString(c.getBlob(c.getColumnIndex("image")), Base64.DEFAULT); 

     image_jo.put("image", encodedImage); 
     image_jo.put("caption", c.getString(c.getColumnIndex("caption"))); 


    } catch (JSONException e) { 
     e.printStackTrace(); 
    } 

    return image_jo; 

}//end get_images_data_JSON 

和POST功能:

public String postData(JSONArray array) { 

    String responseMessage = ""; 

    //set connection timeout values 
    HttpParams myParams = new BasicHttpParams(); 

    //set timeout in milliseconds until a connection is established 
    HttpConnectionParams.setConnectionTimeout(myParams, 10000); 

    //set timeout for waiting data 
    HttpConnectionParams.setSoTimeout(myParams, 10000); 
    HttpClient httpclient = new DefaultHttpClient(myParams); 

    //Get a string out of the JSONArray 
    String json = array.toString(); 

    try { 

     HttpPost httppost = new HttpPost(URL); 
     httppost.setHeader("Content-type", "application/json"); 

     StringEntity se = new StringEntity(json); 
     se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); 
     httppost.setEntity(se); 

     HttpResponse response = httpclient.execute(httppost); 
     InputStream inputStream = response.getEntity().getContent(); 
     responseMessage = inputStreamToString(inputStream); 

     //log out response from server 
     longInfo(responseMessage); 

    } 
    //show error if connection not working 
    catch (SocketTimeoutException e) { 
     e.printStackTrace(); 
     responseMessage = "unreachable"; 

    } 

    catch (ConnectTimeoutException e) { 
     e.printStackTrace(); 
     responseMessage = "unreachable"; 

    } 

    catch (Exception e) { 
     e.printStackTrace(); 
     responseMessage = "unreachable"; 

    } 



    return responseMessage; 

} 

任何帮助,将不胜感激

+0

你应该多考虑。这对你正在尝试做的事更适合。 – njzk2

您的解决方案只是加载所有要发送到内存中的数据。这几乎不可扩展。考虑使用多部分实体。

File image1; 
MultipartEntity entity = new MultipartEntity(); 
entity.addPart("json", new StringBody(serializedJson, Charset.forName("UTF-8")); 
entity.addPart("image1", new FileBody(image1, "application/octet-stream"); 

这个例子显示了我即将发送磁盘上可用文件的情况。通过创建自己的AbstractContentBody实例,你应该能够发送一些东西位于你的分贝,而不消耗太多的内存...

+0

@Vaik:类似https://gist.github.com/2225346 ??? – Mirko

+0

如果你有图像作为文件,那就完美了。如果它们存储在数据库中(如您的示例所示),您可能需要FileBody的子类...或者,您可以将db中的blob写入文件,作为快速入门,并将它们包含为FileBody ... –

+0

可能会改变我的应用程序逻辑并将图像作为设备上的文件,这不是什么大问题。但是,如何发送多个图像的数据,如“标题”和“描述”与他们相关联?一个典型的场景是在单个http请求上上传50/60张图片。 – Mirko

对于任何人来到这里,我解决了所有问题,遵循Vajk的建议,这是我的新POST功能:

public String postData(Cursor images, JSONArray json_array) { 

    int counter = 0; 
    String responseMessage = ""; 

    try { 
     HttpClient httpclient = new DefaultHttpClient(); 
     HttpPost httppost = new HttpPost(URL); 

     //convert JSON array to String 
     String json_encoded_string = json_array.toString(); 

     //MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); 
     MultipartEntity entity = new MultipartEntity(); 

     //add json data 
     entity.addPart("json", new StringBody(json_encoded_string)); 

     //get all images plus data and add them to the Multipart Entity 

     for (images_cursor.moveToFirst(); !images_cursor.isAfterLast(); images_cursor.moveToNext()) { 

      counter++; 

      //Get image as byte array 
      byte[] image_ba = images_cursor.getBlob(images_cursor.getColumnIndex("image")); 
      long image_unit_id = images_cursor.getLong(images_cursor.getColumnIndex("unit_id")); 
      String image_caption = images_cursor.getString(images_cursor.getColumnIndex("caption")); 

      //add image to multipart 
      entity.addPart("image" + counter, new ByteArrayBody(image_ba, "image" + counter + ".jpg")); 

      //add unit _id to multipart 
      entity.addPart("image_unit_id" + counter, new StringBody(String.valueOf(image_unit_id))); 

      //add caption to multipart 
      entity.addPart("image_caption" + counter, new StringBody(String.valueOf(image_caption))); 

     } 

     httppost.setEntity(entity); 

     HttpResponse response = httpclient.execute(httppost); 
     InputStream inputStream = response.getEntity().getContent(); 
     responseMessage = inputStreamToString(inputStream); 

     //log out response from server 
     longInfo(responseMessage); 

    } 
    //show error if connection not working 
    catch (SocketTimeoutException e) { 
     e.printStackTrace(); 
     responseMessage = "unreachable"; 

    } 

    catch (ConnectTimeoutException e) { 
     e.printStackTrace(); 
     responseMessage = "unreachable"; 

    } 

    catch (Exception e) { 
     e.printStackTrace(); 
     responseMessage = "unreachable"; 

    } 

    return responseMessage; 
} 

有人可能会发现这很有用;)