Androidでファイルをアップロードする際にいくつかの問題が発生しています。私はアプリのこのセクションを少しまとめましたが、今は手直しが必要です。
Uri によって参照されるディスク上のイメージから、ファイルをサーバーにアップロードしようとしています。
アップロードする前に、アスペクト比を考慮して、最大サイズの 1280 まで画像を縮小しようとしています。
これは、私が使用している実際のコードを含むサンプル クラスです。私はそれが恐ろしく非効率的だと確信しています:
/**
* This is a fake class, this is actually spread across 2 or 3 files
*/
public class Temp
{
/**
* This is used to return an Input stream of known size
*/
public static class KnownSizeInputStream extends InputStreamBody
{
private int mLength;
public KnownSizeInputStream( final InputStream in, final int length, final String mimeType, final String filename )
{
super( in, mimeType, filename );
mLength = length;
}
public long getContentLength()
{
return mLength;
}
}
private static final int MAX_WIDTH = 1280;
private static final int MAX_HEIGHT = 1280;
/**
* Open up a file on disk and convert it into a stream of known size
*/
public KnownSizeInputStream toStreamAio( Context c, Uri path )
{
/**
* Scale down bitmap
*/
Bitmap bitmapData = null;
try
{
bitmapData = BitmapFactory.decodeStream( c.getContentResolver().openInputStream( path ) );
}
catch( Exception e )
{
e.printStackTrace();
}
int imgWidth = bitmapData.getWidth();
int imgHeight = bitmapData.getHeight();
// Constrain to given size but keep aspect ratio
float scaleFactor = Math.min( ( ( float )MAX_WIDTH ) / imgWidth, ( ( float )MAX_HEIGHT ) / imgHeight );
Matrix scale = new Matrix();
scale.postScale( scaleFactor, scaleFactor );
final Bitmap scaledImage = Bitmap.createBitmap( bitmapData, 0, 0, imgWidth, imgHeight, scale, false );
try
{
bitmapData = scaledImage.copy( scaledImage.getConfig(), true );
scaledImage.recycle();
}
catch( Exception e )
{
e.printStackTrace();
}
/**
* To byte[]
*/
byte[] byteData = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmapData.compress( Bitmap.CompressFormat.JPEG, 100, baos );
byteData = baos.toByteArray();
/**
* To stream
*/
return new KnownSizeInputStream( new ByteArrayInputStream( byteData ), byteData.length, "image/jpg", "Some image" );
}
/**
* Some pieces are removed, the main part is the addPart line
*/
public void doUpload()
{
// create a new HttpPost, to our specified URI
HttpPost post = new HttpPost( postUri );
// org.apache.http.entity.mime
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.STRICT );
// This line starts all of the issues
entity.addPart( "file", toStreamAio( mContext, Uri.parse( "/some/file.jpg" ) ) );
post.setEntity( entity );
// send it
HttpResponse response = client.execute( post );
}
}
これが私が得ている例外です。画像のフルサイズを割り当てようとしているサイズ変更から推測しています:
Caused by: java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCopy(Native Method)
at android.graphics.Bitmap.copy(Bitmap.java:403)
at com.app.helper.UploadableImage.toScaledBitmap(UploadableImage.java:170)
at com.app.helper.UploadableImage.toByteArray(UploadableImage.java:53)
at com.app.helper.UploadableImage.toStream(UploadableImage.java:242)
at com.app.rest.task.UploadContentTask.doInBackground(UploadContentTask.java:80)
at com.app.rest.task.UploadContentTask.doInBackground(UploadContentTask.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:264)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
... 5 more
この行によってトリガーされています:
data = scaledImage.copy( scaledImage.getConfig(), true );
私が求めている主なことは、ディスク上のパスから、スケーリングされたイメージ、そして入れることができるストリームへのイメージをどのように取得するかということだと思います:
org.apache.http.entity.mime.MultipartEntity
経由:
.addPart("file", streamData);
画像が大量になる可能性があると仮定すると、最も効率的です(これまでにヒットした最大のサイズは〜6000pxです)