2012-07-11 41 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%的质量,您也可以实现具有难以察觉的质量损失的良好压缩。您应该尝试质量设置并检查一下自己。