1

JSON と HttpPost を使用して、ローカルの SQLite データベースのコンテンツ全体をリモートの MySQL データベースに送信するアプリケーションのプロトタイプを作成しています。

テキストデータの場合はすべて正常に機能します。今、パーティーに画像を追加しましたが、画像を base64 文字列として、送信している JSON に追加できました。私の画像は 800 x 600 ピクセルで、サイズはそれぞれ 500kb 程度です。

アプリによって手動で生成された JSON を Web ページに貼り付けても問題ありません。画像とその他すべてを取得できます。

アプリのアップロード スクリプトを使用して、4 つの画像を含む JSON 文字列をアップロードしようとしましたが、アプリケーションが進行状況ダイアログでスタックし、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;

}

どんな助けでも大歓迎です

4

2 に答える 2

1

ここに来る人のために、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;
}

誰かがこれが便利だと思うかもしれません;)

于 2012-11-19T13:59:28.887 に答える
1

ソリューションは、送信するすべてのデータをメモリにロードするだけです。それはほとんどスケーラブルではありません。代わりにマルチパート エンティティの使用を検討してください。

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 の独自の実装を作成することにより、大量のメモリを消費することなく、データベースにあるものを送信できるはずです...

于 2012-11-15T15:32:44.353 に答える