图片上传问题

时间:2013-03-15 11:40:17

标签: android encoding picturegallery

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

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

1)如果我尝试使用图库中的图片,我会收到一条带有消息的IOException     / external / images / media / 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);
    }
}
}

这是我将图像(拍摄的照片或图库中)加载到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传输,到目前为止它只将数据放入一个无逻辑的传输对象

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;
    }

我对画廊图片做错了什么?为什么不同图片的编码看起来一样?

2 个答案:

答案 0 :(得分: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);                

}

答案 1 :(得分:0)

我想我终于开始工作了。首先,我使用了Emil的建议并保存了图像。 DCIM_PATH是DCIM文件夹的路径。

public void takePhoto() {
    String directoryPath = DCIM_PATH;
    d("takePhoto directoryPath: " + directoryPath);
    this.pictureFileName = Long.toHexString(System.currentTimeMillis())+".jpg";
    String filePath = directoryPath + pictureFileName ;
    File directory = new File(directoryPath);
    if (!directory.exists()) { // in case there's no DCIM folder
        directory.mkdirs(); // just create it
    }
    d("takePhoto filePath: " + filePath);
    this.imageUri = Uri.parse(filePath);
    d("takePhoto imageUri: " + filePath);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            // here's where I tell the intent where to save the file
    intent.putExtra( 
            MediaStore.EXTRA_OUTPUT,Uri.fromFile( new File(filePath) )
            );

    startActivityForResult(intent, TAKE_PICTURE);

}

我不得不使用两种不同的方法将图片加载到imageview。如果它是刚拍摄的照片,我会用这个:

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的设备媒体数据库的条目。使用该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返回不同:)

希望它可以帮助某人:)