使用 Android-Image-Cropper returns NULL 和 getCroppedImage() 将图像发送到服务器
Sending image to server with Android-Image-Cropper returns NULL with getCroppedImage()
我正在使用 this Github Android Library 裁剪选定的图像。然后将该图像加载到两个 CircleImageView 中并发送到服务器 (PHP)。稍后由数据库中的图像 URL 访问它。实际图像存储在服务器上的文件夹中。
当我在没有 库的情况下使用默认的 onActivityResult 时,一切都很好,但是,较大的图像会被翻转。因此我想使用这个库。
如果我尝试打开上传到服务器的文件,我得到的是:
首先,这是我如何启动 CropImage Activity:
public void showFileChooser() {
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.start(this);
}
这是我的 onActivityResult()
方法和调用的后续方法 uploadAvatar()
。请注意评论说我的位图返回 NULL:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if(resultCode == RESULT_OK) {
picUri = CropImage.getPickImageResultUri(this, data); //get the image URI
Log.d(TAG, "CropImage Result URI: "+picUri);
//THIS RETURNS NULL AND I DON'T KNOW WHY
bitmap = cropImageView.getCroppedImage(); //Assign the bitmap to the cropImageView
Picasso.get().load(picUri).into(edit_profile_avatar); //Load it into the CircleImageView
Picasso.get().load(picUri).into(circle_avatar); //Load it into the DrawerLayout CircleImageView
uploadAvatar(); //Upload to server (see method)
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Exception error = result.getError();
ToastMaker.createLongToast(getApplicationContext(), "Error Cropping Image: "+error);
Log.d(TAG, "Exception: "+error);
}
}
}
public void uploadAvatar() {
//Progress log to show work being done
final ProgressDialog progressDialog = new ProgressDialog(EditProfileActivity.this, R.style.Custom_Progress_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Doing Stuff...");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, uploadAvatarUrl, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
Log.d(TAG, "Volley Response: "+response);
ToastMaker.createLongToast(getApplicationContext(), "Volley Upload Response: "+response);
uploadArray = new JSONArray(response);
JSONObject jsonObject = uploadArray.getJSONObject(0);
String imageString = jsonObject.getString("image");
Log.d(TAG, "imageString: "+imageString);
//Picasso.get().load(imageString).into(edit_profile_avatar);
//Picasso.get().load(imageString).into(circle_avatar);
progressDialog.dismiss();
} catch (Exception e) {
ToastMaker.createLongToast(getApplicationContext(), "Exception: " + e.getMessage());
progressDialog.dismiss();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
ToastMaker.createLongToast(getApplicationContext(), "Volley Error: " + error);
Log.d(TAG, "VolleyError: " + error);
progressDialog.dismiss();
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
//String imageData = imageToString(bitmap);
//params.put("image", imageData);
params.put("image", picUri.toString());
params.put("username", logged_in_username);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(EditProfileActivity.this);
requestQueue.add(stringRequest);
}
如果您注意到,我在 getParams() 方法中留下了注释掉的行,这样您就可以看到我使用的原始方法。这是:
private String imageToString(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
byte[] imageBytes = outputStream.toByteArray();
return Base64.encodeToString(imageBytes, Base64.DEFAULT);
}
如果我尝试在新的 CropImageView 位图上使用该方法,我会收到 NullPointerException。
这是处理它的简短 PHP 脚本。请记住,它在使用此 CropImage 库之前有效。
<?php
include '../../../config/DB.php';
try { $db = new DB(); } catch (Exception $e) { $e->getMessage(); }
if($_SERVER['REQUEST_METHOD'] === 'POST') {
//Get the username for query
$username = $_POST['username'];
//Get the image
$image = $_POST['image'];
//Define upload path
$target_dir = '../../users/'.$username.'/uploads';
//Delete all other files
$files = glob('../../users/'.$username.'/uploads/*');
foreach($files as $file) {
if(is_file($file)) {
unlink($file);
}
}
//Create random number + timestamp for new name
$imageID = rand().'_'.time();
$target_dir = $target_dir .'/'.$imageID.'.jpg';
$db_dir = '../users/'.$username.'/uploads/'.$imageID.'.jpg';
//To see what data is returned
$user_info = array();
//If upload is successful, put the path in the database
if(file_put_contents($target_dir, base64_decode($image))) {
$user_info[] = array('image'=>$db_dir);
$insert = $db->updateRow('UPDATE users SET avatar=? WHERE username=?', [$db_dir, $username]);
echo json_encode($user_info);
} else {
echo json_encode('Error');
}
}
这是写入数据库的内容:
id | username | avatar
1 | username | ../users/username/uploads/2132273469_1546812127.jpg
最后,这是我的日志中返回的内容:
CropImage Result URI: file:///storage/emulated/0/Android/data/com.companyname.appname/cache/pickImageResult.jpeg
Volley Response: [{"image":"..\/users\/username\/uploads\/2132273469_1546812127.jpg"}]
有人用过这个库吗?我在这里错过了什么?该文档没有显示有关上传到服务器的任何内容,仅将 ImageView 设置为位图(有效)。
好的。我需要从 onActivityResult 获取 URI 并将其分配给位图。这就是它返回 null 的原因。
这是我的新 onActivityResult:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
Log.d(TAG, "REQUEST CODE: "+requestCode);
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if(resultCode == RESULT_OK) {
try {
//THIS FIXED IT. NO MORE NULL!
picUri = result.getUri();
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), picUri);
} catch(Exception e) {
ToastMaker.createLongToast(getApplicationContext(), "Exception: "+e.getMessage());
}
edit_profile_avatar.setImageBitmap(bitmap);
circle_avatar.setImageBitmap(bitmap);
uploadAvatar();
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Exception error = result.getError();
ToastMaker.createLongToast(getApplicationContext(), "Error Cropping Image: "+error);
Log.d(TAG, "Exception: "+error);
}
}
}
图像成功加载到 CircleImageView 中,被发送到服务器,并正确显示在相应用户的目录中。
它在数据库中也显示得很好:
mysql> select id, username, avatar from users;
+----+------------------+-------------------------------------------------------+
| id | username | avatar |
+----+------------------+-------------------------------------------------------+
| 1 | username | ../users/username/uploads/1041075557_1546817783.jpeg |
我正在使用 this Github Android Library 裁剪选定的图像。然后将该图像加载到两个 CircleImageView 中并发送到服务器 (PHP)。稍后由数据库中的图像 URL 访问它。实际图像存储在服务器上的文件夹中。
当我在没有 库的情况下使用默认的 onActivityResult 时,一切都很好,但是,较大的图像会被翻转。因此我想使用这个库。
如果我尝试打开上传到服务器的文件,我得到的是:
首先,这是我如何启动 CropImage Activity:
public void showFileChooser() {
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.start(this);
}
这是我的 onActivityResult()
方法和调用的后续方法 uploadAvatar()
。请注意评论说我的位图返回 NULL:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if(resultCode == RESULT_OK) {
picUri = CropImage.getPickImageResultUri(this, data); //get the image URI
Log.d(TAG, "CropImage Result URI: "+picUri);
//THIS RETURNS NULL AND I DON'T KNOW WHY
bitmap = cropImageView.getCroppedImage(); //Assign the bitmap to the cropImageView
Picasso.get().load(picUri).into(edit_profile_avatar); //Load it into the CircleImageView
Picasso.get().load(picUri).into(circle_avatar); //Load it into the DrawerLayout CircleImageView
uploadAvatar(); //Upload to server (see method)
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Exception error = result.getError();
ToastMaker.createLongToast(getApplicationContext(), "Error Cropping Image: "+error);
Log.d(TAG, "Exception: "+error);
}
}
}
public void uploadAvatar() {
//Progress log to show work being done
final ProgressDialog progressDialog = new ProgressDialog(EditProfileActivity.this, R.style.Custom_Progress_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Doing Stuff...");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, uploadAvatarUrl, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
Log.d(TAG, "Volley Response: "+response);
ToastMaker.createLongToast(getApplicationContext(), "Volley Upload Response: "+response);
uploadArray = new JSONArray(response);
JSONObject jsonObject = uploadArray.getJSONObject(0);
String imageString = jsonObject.getString("image");
Log.d(TAG, "imageString: "+imageString);
//Picasso.get().load(imageString).into(edit_profile_avatar);
//Picasso.get().load(imageString).into(circle_avatar);
progressDialog.dismiss();
} catch (Exception e) {
ToastMaker.createLongToast(getApplicationContext(), "Exception: " + e.getMessage());
progressDialog.dismiss();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
ToastMaker.createLongToast(getApplicationContext(), "Volley Error: " + error);
Log.d(TAG, "VolleyError: " + error);
progressDialog.dismiss();
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
//String imageData = imageToString(bitmap);
//params.put("image", imageData);
params.put("image", picUri.toString());
params.put("username", logged_in_username);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(EditProfileActivity.this);
requestQueue.add(stringRequest);
}
如果您注意到,我在 getParams() 方法中留下了注释掉的行,这样您就可以看到我使用的原始方法。这是:
private String imageToString(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
byte[] imageBytes = outputStream.toByteArray();
return Base64.encodeToString(imageBytes, Base64.DEFAULT);
}
如果我尝试在新的 CropImageView 位图上使用该方法,我会收到 NullPointerException。
这是处理它的简短 PHP 脚本。请记住,它在使用此 CropImage 库之前有效。
<?php
include '../../../config/DB.php';
try { $db = new DB(); } catch (Exception $e) { $e->getMessage(); }
if($_SERVER['REQUEST_METHOD'] === 'POST') {
//Get the username for query
$username = $_POST['username'];
//Get the image
$image = $_POST['image'];
//Define upload path
$target_dir = '../../users/'.$username.'/uploads';
//Delete all other files
$files = glob('../../users/'.$username.'/uploads/*');
foreach($files as $file) {
if(is_file($file)) {
unlink($file);
}
}
//Create random number + timestamp for new name
$imageID = rand().'_'.time();
$target_dir = $target_dir .'/'.$imageID.'.jpg';
$db_dir = '../users/'.$username.'/uploads/'.$imageID.'.jpg';
//To see what data is returned
$user_info = array();
//If upload is successful, put the path in the database
if(file_put_contents($target_dir, base64_decode($image))) {
$user_info[] = array('image'=>$db_dir);
$insert = $db->updateRow('UPDATE users SET avatar=? WHERE username=?', [$db_dir, $username]);
echo json_encode($user_info);
} else {
echo json_encode('Error');
}
}
这是写入数据库的内容:
id | username | avatar
1 | username | ../users/username/uploads/2132273469_1546812127.jpg
最后,这是我的日志中返回的内容:
CropImage Result URI: file:///storage/emulated/0/Android/data/com.companyname.appname/cache/pickImageResult.jpeg
Volley Response: [{"image":"..\/users\/username\/uploads\/2132273469_1546812127.jpg"}]
有人用过这个库吗?我在这里错过了什么?该文档没有显示有关上传到服务器的任何内容,仅将 ImageView 设置为位图(有效)。
好的。我需要从 onActivityResult 获取 URI 并将其分配给位图。这就是它返回 null 的原因。
这是我的新 onActivityResult:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
Log.d(TAG, "REQUEST CODE: "+requestCode);
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if(resultCode == RESULT_OK) {
try {
//THIS FIXED IT. NO MORE NULL!
picUri = result.getUri();
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), picUri);
} catch(Exception e) {
ToastMaker.createLongToast(getApplicationContext(), "Exception: "+e.getMessage());
}
edit_profile_avatar.setImageBitmap(bitmap);
circle_avatar.setImageBitmap(bitmap);
uploadAvatar();
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Exception error = result.getError();
ToastMaker.createLongToast(getApplicationContext(), "Error Cropping Image: "+error);
Log.d(TAG, "Exception: "+error);
}
}
}
图像成功加载到 CircleImageView 中,被发送到服务器,并正确显示在相应用户的目录中。
它在数据库中也显示得很好:
mysql> select id, username, avatar from users;
+----+------------------+-------------------------------------------------------+
| id | username | avatar |
+----+------------------+-------------------------------------------------------+
| 1 | username | ../users/username/uploads/1041075557_1546817783.jpeg |