2013-03-15 153 views
0

我有这个活动,用户可以从图库中选择一个图片,或者只是拍一张图片(和其他数据一起)上传到网站。图片上传问题

到目前为止,我遇到了2个不同的问题:

1)如果我从画廊的图片试试吧,我得到一个IOException,使用消息 /外部/图像/媒体/ 2305:开放失败:ENOENT(没有这样的文件或目录) 打开文件流时发生这种情况。

2)如果我尝试采取图片,它会确定,但编码数据串由“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA”(真长,但只有A的)的,我想这不是一个好兆头。这只是一个猜测,因为我仍然无法正确地将其上传到网站,但显示相同数据串的不同图片只是有趣。

这里

@Override 

public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    switch (requestCode) { 
    case TAKE_PICTURE: 
     if (resultCode == Activity.RESULT_OK) { 
      //Uri selectedImage = imageUri; 
      loadImage(imageUri); 

    } 
    break; 
case SELECT_PHOTO: 
    if(resultCode == Activity.RESULT_OK){ 
     imageUri = data.getData(); 
     loadImage(imageUri); 
    } 
} 
} 

代码这是我的加载图像(无论采取或PIC从图库)到ImageView的。它工作正常。

public void loadImage(Uri selectedImage){ 
    mActivity.getContentResolver().notifyChange(selectedImage, null); 

    ContentResolver cr = mActivity.getContentResolver(); 
    Bitmap bitmap; 
    try { 
     bitmap = android.provider.MediaStore.Images.Media 
       .getBitmap(cr, selectedImage); 

     ivPicture.setImageBitmap(bitmap); 
     ivPicture.setVisibility(View.VISIBLE); 
     mActivity.croutonInfo(selectedImage.toString()); 

    } catch (Exception e) { 
     mActivity.croutonAlert("Failed to load"); 
     e("Camera " + e.toString()); 
    } 
} 

这是我用来模拟数据上传的方法。当我得到的API将会有一个的AsyncTask来处理HTTP传输,到目前为止,它只是将数据输入一个logicless传输对象

public void uploadTapa() throws IOException{ 
    mActivity.croutonInfo("subiendo tapa "); 
    d("uploadTapa new "); 
    TapaUploadParametros tup = new TapaUploadParametros(); 
    d("uploadTapa bar: " + nombreBar); 
    tup.setBarNombre(etBarName.getText().toString()); 
    d("uploadTapa tapa: " + nombreTapa); 
    tup.setNombre(etTapaName.getText().toString()); 
    d("uploadTapa municipio: " + municipio); 
    tup.setLocalidad(municipio); 
    d("uploadTapa provincia: " + provincia); 
    tup.setProvincia(provincia); 
    d("uploadTapa tipologiaId: " + tipologiaId); 
    tup.setTipo(tipologiaId); 
    d("uploadTapa precioId: " + precioId); 
    tup.setPrecio(precioId); 

    String encodedImage = encodeImgForHTTP(imageUri); 
    d("uploadTapa encoded image: " + encodedImage); 
    tup.setPic(encodedImage); 
    d("uploadTapa direccionBar: " + direccionBar); 
    tup.setBarDireccion(direccionBar); 
} 

这是为HTTP传输图像进行编码的方法。来自图库的图片仅在“开放流之前”后失败

private String encodeImgForHTTP (Uri imageUri) throws IOException{ 
     ContentResolver cr = mActivity.getContentResolver(); 
     d("encodeImgForHTTP before opening stream "); 
     FileInputStream fis = new FileInputStream(imageUri.getPath()); 
     d("encodeImgForHTTP after opening stream "); 
     // Get binary bytes for encode 
     byte[] imageBytes = new byte[fis.available()]; 
     d("encodeImgForHTTP after getting byte array "); 
     // base 64 encode for text transmission (HTTP) 
     d("encodeImgForHTTP pre 64: " + imageBytes); 
     String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE); 
     d("encodeImgForHTTP before returning the encoded data string " + data_string); 
     return data_string; 
    } 

我在做什么图库图片有问题?为什么不同图片的编码看起来一样?

回答

0

我想我终于它得到工作。首先,我使用了Emil的建议并保存了图像。 DCIM_PATH是DCIM文件夹的路径。我不得不使用两种不同的方法将图片加载到图像视图。如果它只是拍摄的照片,我用这一个:

public void loadImageJustTaken(Uri selectedImage) { 
    mActivity.getContentResolver().notifyChange(selectedImage, null); 

    Bitmap bitmap = 
      BitmapFactory.decodeFile(imageUri.getPath()); 

    ivPicture.setImageBitmap(bitmap); 
    ivPicture.setVisibility(View.VISIBLE); 
} 

而是利用一个从画廊我必须使用ContentResolver的

public void loadImage(Uri selectedImage){ 

    imageUri = selectedImage; 
    mActivity.getContentResolver().notifyChange(selectedImage, null); 

    ContentResolver cr = mActivity.getContentResolver(); 
    Bitmap bitmap; 
    try { 
     bitmap = android.provider.MediaStore.Images.Media 
       .getBitmap(cr, imageUri); 

     ivPicture.setImageBitmap(bitmap); 
     ivPicture.setVisibility(View.VISIBLE); 

     mActivity.croutonInfo(imageUri.getPath()); 

    } catch (Exception e) { 
     e("Camera " + e.toString()); 
    } 
} 

当我要上传的图片,我有编码它。此方法适用,只要你为它提供正确的文件路径

private String encodeImgForHTTP (Uri imageUri) throws IOException{ 
    String realPicPath = getPath(imageUri); 
    d("encodeImgForHTTP before opening stream " + realPicPath); 
    FileInputStream fis = new FileInputStream(realPicPath); 
    d("encodeImgForHTTP after opening stream "); 
    // Get binary bytes for encode 
    byte[] imageBytes = IOUtils.toByteArray(fis); 
    d("encodeImgForHTTP after getting byte array "); 

    // base 64 encode for text transmission (HTTP) 
    //String data_string = Base64.encodeToString(data, Base64.URL_SAFE); 
    d("encodeImgForHTTP pre 64: " + imageBytes); 
    String data_string = Base64.encodeToString(imageBytes, Base64.URL_SAFE); 
    d("encodeImgForHTTP before returning the encoded data string " + data_string); 
    return data_string; 
} 

这里就是我得到的图片“真实路径”:

public String getPath(Uri uri) throws IOException { 
    String[] projection = { MediaStore.Images.Media.DATA }; 
    Cursor cursor = mActivity. 
      managedQuery(uri, projection, null, null, null); 
    if (cursor == null){ // with pictures just taken, the uri returned by the onActivityResult makes cursor to be null. Following method takes care of that 
     uri = saveMediaEntry(imageUri.getPath(), pictureFileName, ""); 
     d("cursor nulo, segundo cursor con uri " + uri.getPath()); 
     cursor = mActivity. 
       managedQuery(uri, projection, null, null, null); 
    } 
    int column_index = cursor 
      .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 
    cursor.moveToFirst(); 
    return cursor.getString(column_index); 
} 

的方法saveMediaEntry创建的条目设备的媒体数据库返回其Uri。使用开放的,现在光标将指向图片文件,我们希望

private Uri saveMediaEntry(
     String imagePath,String title,String description) throws IOException { 

    ExifInterface exif = new ExifInterface(imagePath); 

    ContentValues v = new ContentValues(); 
    v.put(Images.Media.TITLE, title); 
    v.put(Images.Media.DISPLAY_NAME, title); 
    v.put(Images.Media.DESCRIPTION, description); 
    v.put(Images.Media.DATE_ADDED, System.currentTimeMillis()); 
    v.put(Images.Media.DATE_TAKEN, exif.getAttribute(ExifInterface.TAG_DATETIME)); 
    //v.put(Images.Media.DATE_MODIFIED, dateTaken) ; 
    v.put(Images.Media.MIME_TYPE, "image/jpeg"); 
    v.put(Images.Media.ORIENTATION, exif.getAttribute(ExifInterface.TAG_ORIENTATION)); 
    File f = new File(imagePath) ; 
    File parent = f.getParentFile() ; 
    String path = parent.toString().toLowerCase() ; 
    String name = parent.getName().toLowerCase() ; 
    v.put(Images.ImageColumns.BUCKET_ID, path.hashCode()); 
    v.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name); 
    v.put(Images.Media.SIZE,f.length()) ; 
    f = null ; 

    v.put(Images.Media.LATITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE)); 
    v.put(Images.Media.LONGITUDE, exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE)); 

    v.put("_data",imagePath) ; 
    ContentResolver c = mActivity.getContentResolver() ; 
    return c.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, v); 
} 

这一切后,得到的图片加载OK,和Base64.encodeToString回报不同的画面是不同的:)

希望它帮助某人:)

1

我认为你应该把你的输入流缓冲到较小的字节数组中,而不是在你的编码函数中使用available函数作为开始。

为了照顾你要确定,你想保存的图像,并传递作为额外的意图,例如路径图片:

private void capture(){ 
    String directoryPath = Environment.getExternalStorageDirectory() + "/" + IMAGE_DIRECTORY + "/"; 
    String filePath = directoryPath+Long.toHexString(System.currentTimeMillis())+".jpg"; 
    File directory = new File(directoryPath); 
    if (!directory.exists()) { 
     directory.mkdirs(); 
    } 
    this.capturePath = filePath; // you will process the image from this path if the capture goes well 
    Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(filePath))); 
    startActivityForResult(intent, REQUEST_CAPTURE);     

} 
+0

是的,我非常确定(因为我在编码文件等方面完全是绿色的),这里有很大的改进空间。我只是想用本地资源实现它,因为我发现的大多数示例都使用了来自apache等的外部库(并且我已经在这个应用中使用了很多例子)。 关于图片:我是否需要保存图片才能上传图片?从相机意图中获得的临时uri无效吗? – Frank 2013-03-15 12:24:46

+0

@Frank我不记得任何来自相机意图的临时URI,但我会告诉你,设备之间的捕获行为存在很多不一致之处。例如,这里是我尝试实现它时遇到的问题:http://stackoverflow.com/questions/6390163/deleting-a-gallery-image-after-camera-intent-photo-taken/8555925#8555925 – 2013-03-15 12:30:20

+0

我' m试试这个片段,现在它不会响应我拍摄照片后按下“检查”。屏幕仍然在拍摄的照片上。如果我按“X”取消并返回到我的活动,它确实有效...... – Frank 2013-03-18 12:03:49