2

私のsdcardからphpサーバーに画像を送信しようとしています... 2つのクラスを作成します.1つ目はMainActivity.javaで、2つ目はBase64.javaで、Base64形式でバイトをエンコードします。

私の MainActivity.java は次のとおりです。

public class MainActivity extends Activity {
    InputStream inputStream;
    @Override
public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_main);

        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/DCIM/Camera/1378889572299.jpg");
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); //compress to which format you want.
        byte [] byte_arr = stream.toByteArray();
        String image_str = Base64.encodeBytes(byte_arr);
         ArrayList<NameValuePair> nameValuePairs = new  ArrayList<NameValuePair>();

        nameValuePairs.add(new BasicNameValuePair("image",image_str));
Log.e("ok", "1");
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://myserver.com/upload_image.php");
Log.e("ok", "3");
try {
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
Log.e("ok", "4");
HttpResponse response = httpclient.execute(httppost);
Log.e("ok", "5");

    String the_string_response = convertResponseToString(response);
} catch (IllegalStateException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

    }

    public String convertResponseToString(HttpResponse response) throws IllegalStateException, IOException{

        String res = "";
         StringBuffer buffer = new StringBuffer();
         inputStream = response.getEntity().getContent();
         final int contentLength = (int) response.getEntity().getContentLength(); //getting content length…..
          runOnUiThread(new Runnable() {

        @Override
        public void run() {
            Toast.makeText(MainActivity.this, "contentLength : " + contentLength, Toast.LENGTH_LONG).show();                    
        }
    });

         if (contentLength < 0){
         }
         else{
                byte[] data = new byte[512];
                int len = 0;
                try
                {
                    while (-1 != (len = inputStream.read(data)) )
                    {
                        buffer.append(new String(data, 0, len)); //converting to string and appending  to stringbuffer…..
                    }
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
                try
                {
                    inputStream.close(); // closing the stream…..
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
                res = buffer.toString();     // converting stringbuffer to string…..
                final String res2 = res;
                runOnUiThread(new Runnable() {

                @Override
                public void run() {
                   Toast.makeText(MainActivity.this, "Result : " + res2, Toast.LENGTH_LONG).show();
                }
            });
                //System.out.println("Response => " +  EntityUtils.toString(response.getEntity()));
         }
         return res;
    }
}

私はこのエラーを持っています:

........OutOfMemoryError
….at java.lang.AbstractStringBuilder.(AbstractStringBuilder.java:81)
….at java.lang.StringBuilder.(StringBuilder.java:68)
….at java.net.URLEncoder.encode(URLEncoder.java:98)
….at org.apache.http.client.utils.URLEncodedUtils.encode(URLEncodedUtils.java:184)
….at org.apache.http.client.utils.URLEncodedUtils.format(URLEncodedUtils.java:163)
….at org.apache.http.client.entity.UrlEncodedFormEntity.(UrlEncodedFormEntity.java:71)
….at com.example.imageuploadonserver.MainActivity.onCreate(MainActivity.java:43)

43 行目: httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

コードにいくつかの変更を加えます...そして、画像ソースをSDカードから drawabel.ic_luncher に置き換えます:

Bitmap bitmap = BitmapFactory.decodeFile(“/sdcard/DCIM/Camera/1378889572299.jpg”);

これで :

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);

そしてそれはうまくいきます!!!!

私はたくさんグーグルで検索しましたが、間違ったキーワードを使用したか、インターネット上に簡単な解決策がありません. ここの誰かが私を助けてくれることを願っています。

Fadel さん、よろしくお願いします。

4

4 に答える 4

3

あなたのカメラからの写真なので、あなたの画像は約5Moだとしましょう。

  1. ビットマップとしてロードすると、ヒープ サイズが 5Mo 増加します。
  2. 次に、som 圧縮を使用してバイト配列に変換すると、ヒープ サイズが再び 4Mo 増加する => 9Mo になります。
  3. 次に、それを文字列にbase64エンコードすると、ヒープは4Mo => 13Mo増加します
  4. 次に、それを NameValu¨Pair に文字列として追加することで、文字列がコピーされ (ここではわかりません)、ヒープが再び大きくなると思います => 17Mo
  5. そして、それをエンティティとして追加すると、コンテンツがエンコードされ、ヒープが再び増加します => 22Mo

もう必要なくなったら、メモリを解放してみてください。

  1. ステップ 2 の後に bitmap.recycle() を使用します。
  2. ステップ 3 の後で一口配列を null に設定します
  3. ステップ4の後に文字列をnullに設定します(不明)

そうすることで9~14Moくらいリリースすることになります

ただし、いずれの場合も、エンコード (base64Encode または UrlEncode) すると、ヒープ サイズがビットマップ サイズの 2 倍になります。より良い方法は、ファイルのコンテンツを HTTP ストリームに書き込み、ファイルから読み取ることです。

于 2013-09-11T16:47:33.293 に答える
0

一度にすべてのデータをメモリにロードすることを避けるために、チャンクでデータをストリーミングするChunkedOutputStream を使用します。これに注意すれば、すべてをメモリに保存する必要がないため、無制限のサイズの画像をアップロードできます。

于 2013-09-11T17:14:12.860 に答える
0

Client <-> Server WebServices を扱う場合、要求または応答データ全体を String または任意のメモリ オブジェクトにロードすることは悪い習慣であり、できる限り避ける必要があります。多くのシナリオで回避可能です。

なぜそれを避けるべきですか?

多くのシナリオでは、データのサイズに関する保証がなく、OOM 例外が発生することがよくあります。

どうすればいいですか?

ほとんどの要求データは、送信中に構築でき (XML、JSON、Whatever シリアル化)、シリアル化するためにメモリ内の構造全体をリードする必要はありません。

ほとんどの回答データでは、オブジェクトをストリームから解析してデータベースに保存するか、ストリームの不要な部分を破棄できます。応答全体を文字列としてロードせずに。

あなたの特定のケースでは、圧縮したい画像であるディスク上のファイルがあります。標準ライブラリまたはその他の画像ライブラリを使用して、別のファイルに 90% JPEG に変換します。次に、ファイルを httpPost.entity の出力ストリームに直接ストリーミングできます。

一部のライブラリ (おそらく標準ライブラリでさえありますか?) は、最初の画像ファイルから直接、圧縮された画像を使用して InputStream を取得する可能性を提供する可能性さえあります。

どちらの場合も、最初の InputStream を Base64 変換を行う別の InputStream にカプセル化すると、そこに到達します。

そうすれば、ストリーム バッファのために一度に数キロバイト以上をメモリにロードする必要がなくなります。

于 2013-09-11T17:54:31.997 に答える