Simple&Natural

ImageCropper Lib와 okHttp3를 이용한 이미지 서버 업로드 본문

안드로이드(Android)/이슈 및 해결

ImageCropper Lib와 okHttp3를 이용한 이미지 서버 업로드

Essense 2019. 12. 13. 13:45
728x90

본 포스팅은 2018. 12. 4. 0:11 네이버 블로그에 작성했던 글을 이전한 것임

 

 

 

 

 

 

 

 

 

ImageCropper를 이용하여 이미지를 수정 및 받아오고 okHttp3를 통해 서버에 업로드하는 과정이 필요했다.

매우 많은 우여곡절 끝에... (결론적으로 파일객체 생성과 php권한 및 용량 문제가 메인이었음...)

성공하게 되었다.

 

기본적으로 핵심 원리는

1. 이미지의 경로를 불러오고

2. 이를 이용하여 파일 객체를 생성한 다음

3. Http 통신을 사용하여 서버에 업로드

로 구분된다.

 

ImageCropper 라이브러리는 수정된 이미지를 갤러리가 아닌 Cache 폴더에 저장하게 된다.

경로를 찾아보면 휴대폰에서 직접 찾아 들어간다는 기준 하에 "Android/data/패키지명/Cache/pickImageResult.jpeg"

로 저장된다. 하지만 여기서 이 경로를 직접 사용하여 파일 객체를 만들게 되면 카메라로 촬영한 사진만 있고

갤러리에서 불러온 것은 보이지 않는다... 그럼 이놈은 어디에 저장되는 건지 아직도 오리무중;;

 

이건 나중에 해결하기로 하고 일단 카메라와 갤러리를 통해 작업한 이미지를 전부 불러올 수 있게 하려면

onActivityResult에서 Intent 파라미터로 저장된 data를 통해 uri를 얻어야 한다.

이 uri를 또 그냥 갖다가 넣으면 파일 객체는 만들어지지 않고 반드시 getPath를 통해 얻은 경로를 넣어줘야 한다.

사실 파일만 잘 만들 수 있으면 Http로 서버에 던져버리는 건 별로 어렵지 않다. (안드로이드 스튜디오 내에서는...)

 

이후에 문제가 생길만한 부분은 리눅스 폴더권한과 php파일 용량 제한 정도일까?

반드시 이부분을 꼭 확인하도록 하자.

권한 부분은 리눅스 log 폴더에 error.log를 보면 대충 permission denied라고 친절하게 알려주는데

 

이 용량문제는 로그도 안찍어줘서 혼자 머리싸매고 고민하다가 문득 이거아닐까 싶어서 보다가 해결했다.

어떤 이미지는 올라가고 어떤 건 또 올라가지를 않아서 왜그럴까에서 힌트를 얻음.

내 경우에는 2MB가 제한용량이었는데 3MB를 처넣으려고 했으니 올라갈리가 있나...

 

아무튼 이미지 업로드 문제는 여기까지 해서 대충 끝냈다.

 

 

 

 

 

 

 

 

 

 

<라이브러리 build 시 소스>

implementation("com.squareup.okhttp3:okhttp:3.12.0")

api 'com.theartofdev.edmodo:android-image-cropper:2.8.+'

 

CropImageView.CropResult result = CropImage.getActivityResult(data);

여기서 data는 onActivityResult의 Intent 파라미터임

 

 

Uri resultUri = result.getUri();

Uri resultOriginalUri = result.getOriginalUri();

String getUriPath = resultUri.getPath(); //파일생성 가능

String getOriginalUriPath = resultOriginalUri.getPath();

Log.d("test3", "result uri : " + resultUri.toString());

Log.d("test3", "result original uri : " + resultOriginalUri.toString());

Log.d("test3", "result uri path : " + getUriPath);

Log.d("test3", "result original path : " + getOriginalUriPath);

 

 

 

test3의 로그는 다음과 같다.

<카메라를 이용해 촬영한 사진>

result uri : file:///data/user/0/com.example.msg_b.librarytest/cache/cropped4137546372064436160.jpg

result original uri : file:///storage/emulated/0/Android/data/com.example.msg_b.librarytest/cache/pickImageResult.jpeg

result uri path : /data/user/0/com.example.msg_b.librarytest/cache/cropped4137546372064436160.jpg

result original path : /storage/emulated/0/Android/data/com.example.msg_b.librarytest/cache/pickImageResult.jpeg

 

<갤러리 에서 가져온 사진>

result uri : file:///data/user/0/com.example.msg_b.librarytest/cache/cropped6146047158517801312.jpg

result original uri : content://media/external/images/media/6599

result uri path : /data/user/0/com.example.msg_b.librarytest/cache/cropped6146047158517801312.jpg

result original path : /external/images/media/6599

 

 

 

 

 

총 핵심사항 정리

 

1. btn_upload 버튼에 ImageCropper를 실행

 

btn_upload.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

CropImage.activity().start(MainActivity.this);

}

});

 

 

 

 

 

2. onActivityResult에서 작업한 이미지의 경로를 받아온 후 MyImgTask에 파라미터로 보냄.

중간에 AbsoluteCacheUri는 직접 디바이스에서 찾은 CroppedImage의 경로인데

이 경로를 쓰면 카메라로 촬영한 사진만 저장되고 갤러리에서 가져온 사진은 불러오지 못함.

CropImage.getActivityResult(data).getUri().getPath(); 를 이용해 얻은 경로를 넣어주면

카메라와 갤러리 작업물 둘다 불러올 수 있음.

 

 

 

@Override

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

super.onActivityResult(requestCode, resultCode, data);

 

if (resultCode == RESULT_OK) {

 

CropImageView.CropResult result = CropImage.getActivityResult(data);

 

Uri resultUri = result.getUri();

Uri resultOriginalUri = result.getOriginalUri();

String getUriPath = resultUri.getPath();

String getOriginalUriPath = resultOriginalUri.getPath();

Log.d("test3", "result uri : " + resultUri.toString());

Log.d("test3", "result original uri : " + resultOriginalUri.toString());

Log.d("test3", "result uri path : " + getUriPath);

Log.d("test3", "result original path : " + getOriginalUriPath);

 

String AbsoluteCacheUri = Environment.getExternalStorageDirectory().getAbsolutePath()

+ "/Android/data/"

+ getApplicationContext().getPackageName()

+ "/cache/pickImageResult.jpeg";

Log.d("test4", AbsoluteCacheUri);

 

new MyImgTask(getUriPath).execute();

 

} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {

}

 

}

 

 

 

 

 

3. 최종적으로 네트워크 통신을 통하여 이미지를 서버에 전송하고 json형태로 응답을 받아오는 AsyncTask임.

 

 

/** 이미지 웹서버 업로드 태스크 **/

 

 

class MyImgTask extends AsyncTask<String, Void, String> {

 

private String Path;

 

public MyImgTask(String path) {

this.Path = path;

}

 

 

ProgressDialog mDialog = new ProgressDialog(MainActivity.this);

 

@Override

protected void onPreExecute() {

super.onPreExecute();

 

 

mDialog.show();

}

 

 

@Override

protected String doInBackground(String... strings) {

 

File srcFile = new File(Path);

String result = null;

 

if(srcFile.exists()){ // 파일이 존재하는 경우

if(srcFile.isFile()){ //파일이 맞으면

RequestBody requestBody = new MultipartBody.Builder()

.setType(MultipartBody.FORM)

.addFormDataPart("file", "test2", RequestBody.create(MediaType.parse("image/jpg"), srcFile))

.build();

 

Request request = new Request.Builder()

.url("내 php파일 경로")

.post(requestBody)

.build();

 

Call call = new OkHttpClient().newCall(request);

Log.d("filetest", request.body().toString());

 

try {

Response response = call.execute();

result = response.body().string();

} catch (IOException e) {

e.printStackTrace();

Log.d("filetest", "try 실패 : " + e.toString());

}

}

else { // 이거 파일이 아닌데?

Log.d("filetest", "이거 파일 아닌데?");

}

}

else {

Log.d("filetest", "파일이 없는데?");

}

return result;

}

 

@Override

protected void onPostExecute(String s) {

super.onPostExecute(s);

Log.d("filetest", "response : "+s);

mDialog.dismiss();

}

}

 

 

 

 

4. php파일은 다음과 같음

권한과 uploaded file의 max size는 필히 리눅스에서 설정해줘야함.

 

<?php

$target_dir = "";

$target_file_name =$target_dir .basename($_FILES["file"]["name"].".jpg");

$response = array();

 

 

//Check if image file is a actual image or fake image

if(isset($_FILES["file"])) {

if(move_uploaded_file($_FILES["file"]["tmp_name"], $target_file_name)) {

$success = true;

$message = "successfully uploaded";

} else {

$success = false;

$message = "Error while uploading";

}

} else {

$success = false;

$message = "Required Field Missing";

}

$response["success"] = $success;

$response["message"] = $message;

echo json_encode($response);

?>

 

 

------------------------------------------------------------------------------------------------------------------------

<2018-12-04 추가내용>

 

- 파일객체 생성 가능한 경로 최종 정리

 

String croppedPath = result.getUri().getPath(); /** 가능 **/

String croppedOriginalPath = result.getOriginalUri().getPath(); /** 가능 **/

String croppedUri = result.getUri().toString(); /** 불가능 **/

String croppedOriginalUri = result.getOriginalUri().toString(); /** 불가능 **/

 

Log.d("filetest", "Path : " + croppedPath);

Log.d("filetest", "Original Path : " + croppedOriginalPath);

Log.d("filetest", "Uri : " + croppedUri);

Log.d("filetest", "Original Uri : " + croppedOriginalUri);

 

 

 

 

728x90