2012-07-11 64 views
2

我遇到一些問題,在Android上上傳文件。我在應用程序的這一部分拼湊了一些,現在需要一些修改。Android - 從磁盤上傳圖片

我試圖從U盤引用的磁盤映像上傳文件到服務器。

之前上傳,我試圖縮小圖片,尊重縱橫比,以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是最大尺寸到目前爲止,我已經打了)

回答

0

這是現在正在爲我工​​作的完整課程。使用Context和Uri加載它,並調用以下三種公共方法中的任意一種:

public class UploadableImage 
{ 
    private static final int MAX_WIDTH = 1280; 
    private static final int MAX_HEIGHT = 1280; 

    private Uri    mUri; 

    private String   mImageName; 

    private Context   mContext; 

    public UploadableImage(Context context) 
    { 
    mContext = context; 

    generateFilename(); 
    } 

    public UploadableImage(Context context, Uri uri) 
    { 
    mContext = context; 
    mUri = uri; 

    generateFilename(); 
    } 

    // TODO Generate... 
    private void generateFilename() 
    { 
    mImageName = UUID.randomUUID().toString() + ".jpg"; 
    } 

    public void setUri(Uri uri) 
    { 
    mUri = uri; 
    } 

    public Bitmap toBitmap() 
    { 
    try 
    { 
     InputStream input = mContext.getContentResolver().openInputStream(mUri); 

     BitmapFactory.Options readOptions = new BitmapFactory.Options(); 
     readOptions.inJustDecodeBounds = true; 

     BitmapFactory.decodeStream(input, null, readOptions); 

     input.close(); 

     // Raw height and width of image 
     final int height = readOptions.outHeight; 
     final int width = readOptions.outWidth; 

     int inSampleSize = 1; 

     if(height > MAX_HEIGHT || width > MAX_WIDTH) 
     { 
     if(width > height) 
     { 
      float result = (float)height/(float)MAX_HEIGHT; 

      inSampleSize = (int)FloatMath.ceil(result); 
     } 
     else 
     { 
      float result = (float)width/(float)MAX_WIDTH; 

      inSampleSize = (int)FloatMath.ceil(result); 
     } 
     } 

     return toBitmap(inSampleSize); 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 

    return null; 
    } 

    public Bitmap toBitmap(int sampleSize) 
    { 
    try 
    { 
     InputStream input = mContext.getContentResolver().openInputStream(mUri); 

     input = mContext.getContentResolver().openInputStream(mUri); 

     // Decode bitmap with inSampleSize set 
     BitmapFactory.Options scaleOptions = new BitmapFactory.Options(); 

     scaleOptions.inJustDecodeBounds = false; 
     scaleOptions.inSampleSize = sampleSize; 

     Bitmap scaledBitmap = BitmapFactory.decodeStream(input, null, scaleOptions); 

     input.close(); 

     return scaledBitmap; 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 

    return null; 
    } 

    public KnownSizeInputStream toMimeStream() 
    { 
    Bitmap scaledBitmap = toBitmap(); 

    ByteArrayOutputStream stream = new ByteArrayOutputStream(); 

    scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 95, stream); 

    byte[] byteArray = stream.toByteArray(); 

    return new KnownSizeInputStream(new ByteArrayInputStream(byteArray), byteArray.length, "image/jpg", mImageName); 
    } 

    public String toString() 
    { 
    return "UploadableImage, Uri: " + mUri; 
    } 
} 
1

首先,爲什麼你必須做出縮放位圖的副本?你能不能縮放位圖直接這樣壓縮:

final Bitmap scaledImage = Bitmap.createBitmap(bitmapData, 0, 0, 
     imgWidth, imgHeight, scale, false); 
scaledImage.compress(Bitmap.CompressFormat.JPEG, 100, baos); 

如果你能避免拷貝,你可以避開得到OutOfMemoryError

即使使用JPEG壓縮(使用自然物體的照片進行處理時)選擇95%的質量,您也可以實現具有難以察覺的質量損失的良好壓縮。您應該嘗試質量設置並檢查一下自己。