2016-06-01 16 views
0

android.hardware.Camera APIを使用して写真を撮ります。次に、それを実際のサイズの半分のビットマップに変換し、JPEGの品質80に圧縮し、Base64に変換し、次のようにサーバーに送信します。Base64でサーバーに大きな画像をアップロード

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream); 
byte[] byteArray = byteArrayOutputStream.toByteArray(); 
String encoded = Base64.encodeToString(byteArray, Base64.NO_WRAP); 
String json_response = ""; 

try { 
    URL url = new URL("https://example.com/api_endpoint"); 
    HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
    conn.setReadTimeout(15000); 
    conn.setConnectTimeout(15000); 
    conn.setRequestMethod("POST"); 
    conn.setDoInput(true); 
    conn.setDoOutput(true); 
    OutputStream os = conn.getOutputStream(); 
    BufferedWriter writer = new BufferedWriter(
      new OutputStreamWriter(os, "UTF-8")); 
    writer.write("?reg=" + regCode); 
    writer.write("&img=" + encoded); 
    writer.flush(); 
    writer.close(); 
    os.close(); 
    Log.d("Auth", conn.getResponseCode() + ""); 
    InputStreamReader in = new InputStreamReader(conn.getInputStream()); 
    BufferedReader br = new BufferedReader(in); 
    String text = ""; 
    while ((text = br.readLine()) != null) { 
     json_response += text; 
    } 
    conn.disconnect(); 
} catch (IOException e) { 
    Log.d(getClass().getName(), "" + e.getMessage()); 
} 

期待どおりに動作します。今、画像のサイズを変更せずに品質を100%に保っていない場合、どうすればOutOfMemoryErrorを避けることができますか?私のアプリケーションでは、イメージが完全な解像度と最高品質で表示される必要があります。

私の質問は以下のとおりです。

  1. は、私は正しい道をアップロードしています方法は何ですか?
  2. 送信方法画像はOutOfMemoryErrorなしで最高の品質です。つまり、このプロセスでRAMの使用を最適化する方法はありますか?
+0

男性は他の賢明なあなたのアプリのサイズを変更し、このことができます...私に教えてくださいクラッシュする。 Base64で変換する前にそれをサイズ変更 –

+0

こんにちは!ありがとうございますが、それは私がすでにやったことです。今私はサイズ変更せずに転送する必要があります。 –

+0

それからクラッシュする可能性が90%を超えたり、写真がアップロードに時間がかかることがあります。 –

答えて

1

APIエンドポイントを管理している場合は、次に、クライアント側からのマルチパートアップロードを受け入れるPOSTリクエストを実装しようとします。ここでは、クライアント側では

、(Okhttpクライアントで)APIに画像をアップロードするには、このような何かを持っている

private static final String IMGUR_CLIENT_ID = "..."; 
    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); 

    private final OkHttpClient client = new OkHttpClient(); 

    public void run() throws Exception { 
    // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image 
    RequestBody requestBody = new MultipartBody.Builder() 
     .setType(MultipartBody.FORM) 
     .addFormDataPart("title", "Square Logo") 
     .addFormDataPart("image", "logo-square.png", 
      RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png"))) 
     .build(); 

    Request request = new Request.Builder() 
     .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID) 
     .url("https://api.imgur.com/3/image") 
     .post(requestBody) 
     .build(); 

    Response response = client.newCall(request).execute(); 
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); 

    System.out.println(response.body().string()); 
    } 
+0

「クライアント側から複数パートのアップロードを受け入れるPOST要求を実装する」はどうすればよいですか?いくつかのリソースを指摘できますか? また、 'RequestBody.create(MEDIA_TYPE_PNG、new File(" website/static/logo-square.png "))'のファイルから読み込んでいるので、撮影した画像を保存する必要がありますアップロードに進む前にファイルに貼り付けますか? –

+0

これは、コードスニペットはOkHttpClientで投稿する例でしたが、あなたはAndroidアプリでそれを持つように調整することができます。 – toantran

+0

はい、まずストレージに保存する必要があります。 OutOfMemoryの問題を引き起こす可能性のあるすべてのデータをメモリに保存しないようにすることです(この問題は望ましくありません)。 – toantran

2

は私のイメージ/ファイルアップローダークラスです:

public class ImageUploader extends AsyncTask<String, String, String> { 

    File imageFile = null; 
    String fileName = null; 

    public ImageUploader(File imageFile, String fileName){ 
     this.imageFile = imageFile; 
     this.fileName = fileName; 
    } 

    @Override 
    protected String doInBackground(String... params) { 
     String url_str = params[0]; 

     String lineEnd = "\r\n"; 
     String twoHyphens = "--"; 
     String boundary = "*****"; 
     String Tag="fSnd"; 

     try { 
      URL url = new URL(url_str); 
      HttpURLConnection c = (HttpURLConnection) url.openConnection(); 

      c.setRequestMethod("POST"); 

      c.setDoInput(true); 
      c.setDoOutput(true); 

      c.setRequestProperty("Connection", "Keep-Alive"); 
      c.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); 

      c.connect(); 

      DataOutputStream dos = new DataOutputStream(c.getOutputStream()); 

      dos.writeBytes(twoHyphens + boundary + lineEnd); 
      dos.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + this.fileName + "\"" + lineEnd); 
      dos.writeBytes(lineEnd); 

      FileInputStream fin = new FileInputStream(imageFile); 

      int bytesAvailable = fin.available(); 

      int maxBufferSize = 1024; 
      int bufferSize = Math.min(bytesAvailable, maxBufferSize); 
      byte[ ] buffer = new byte[bufferSize]; 

      int bytesRead = fin.read(buffer, 0, bufferSize); 

      while (bytesRead > 0) 
      { 
       dos.write(buffer, 0, bufferSize); 
       bytesAvailable = fin.available(); 
       bufferSize = Math.min(bytesAvailable,maxBufferSize); 
       bytesRead = fin.read(buffer, 0,bufferSize); 
      } 


      dos.writeBytes(lineEnd); 
      dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); 

      fin.close(); 
      dos.flush(); 
      dos.close(); 

      StringBuilder response = new StringBuilder(); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(c.getInputStream())); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       response.append(line); 
      } 

      return response.toString(); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (ProtocolException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 

     } 

     return null; 
    } 
} 

用途:

new ImageUploader(pictureFile, "sample.jpg"){ 
    @Override 
    protected void onPostExecute(String s) { 
     super.onPostExecute(s); 
     Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show(); 
    } 
}.execute("http://example/upload.php"); 

PHP:

<?php 
    $file = explode('.', $_FILES['file']['name']); 
    $ext = $file[count($file) - 1]; 
    $name = substr($_FILES['file']['name'], 0, (strlen($ext) + 1) * -1); 
    $location = 'images/'; 
    $cntr = 1; 
    $tmp_name = $name; 
    if(move_uploaded_file($_FILES['file']['tmp_name'], $location.$tmp_name.'.'.$ext)){ 
     echo "Image was uploaded."; 
    }else{ 
     echo "Image was not uploaded."; 
    } 
?> 
0

サーバーにダウンロードしても問題ではないと思います。私が正しく理解すれば、カメラから画像を取得して送信します。ビットマップイメージ - - 場合は、onActivityResult()に戻す単純な要求の意図、使用していることを注意、それはテント()メソッドに別のフォームを使用しますこれはOutOfMemoryException例外の点であってもよい...

ソリューションを、(それを得ることができます彼のパラメータにはストレージパスがあります)、ビットマップイメージは返されません。しかし、あなたが指定したパスに写真を保存してください。そして今、あなたはOutOfMemoryExceptionがなくて、パスに写真で何かを行うことができます...

正しい意思を開始するサンプル:

File destination = new File(Environment.getExternalStorageDirectory(), 
          "image.jpg"); 

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
       intent.putExtra(MediaStore.EXTRA_OUTPUT, 
       Uri.fromFile(destination)); 
startActivityForResult(intent, CAMERA_PICTURE); 

関連する問題