各位大大晚安
最近在練習取得相簿內照片,並且上傳到server
我使用的是Retrofit
但是一直不成功,印出的errorBody如下
<!doctype html>
以下是code(省略了一些不相關的)
拿到相簿的照片並轉換成MultipartBody.Part
class ProfileFragment : Fragment() {
companion object {
const val REQUEST_FROM_CAMERA = 1001
const val REQUEST_FROM_GALLERY = 1002
}
var saveUri: Uri? = null
var realUri: String = ""
var bitmap: ByteArray? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val checkSelfPermission = ActivityCompat.checkSelfPermission(requireActivity(), android.Manifest.permission.CAMERA)
if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
permissionPhoto()
} else {
}
binding.btnPickImage.setOnClickListener {
openAlbum()
}
binding.btnTakePicture.setOnClickListener {
openCamera()
}
return binding.root
}
fun permissionPhoto() {
ActivityCompat.requestPermissions(requireActivity(),
arrayOf(android.Manifest.permission.CAMERA,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_EXTERNAL_STORAGE), 0)
}
private fun openCamera() {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val tmpFile =
File(Environment.getExternalStorageDirectory().toString(),
System.currentTimeMillis().toString() + ".jpg")
realUri = tmpFile.path
val uriForCamera = FileProvider.getUriForFile(requireActivity(),
"com.example.bookreports.provider", tmpFile)
saveUri = uriForCamera
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForCamera)
startActivityForResult(intent, REQUEST_FROM_CAMERA)
}
private fun openAlbum() {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.setType("image/*")
startActivityForResult(intent, REQUEST_FROM_GALLERY)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when(requestCode){
CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE ->{
var result = CropImage.getActivityResult(data)
if(resultCode == Activity.RESULT_OK){
val resultUri = result.uri
val file = File(resultUri.path)
var requestFile =
file.asRequestBody("image/*".toMediaTypeOrNull())
var body: MultipartBody.Part = MultipartBody.Part.createFormData("image",file.name,requestFile)
Timber.d("result : $result")
Timber.d("resultUri : $$resultUri")
Timber.d("file $file")
Timber.d("requestFile : $requestFile")
Timber.d("body $body")
viewModel.uploadImage(body)
}
}
REQUEST_FROM_GALLERY ->{
when(resultCode){
Activity.RESULT_OK ->{
val uri = data?.data
getContext()?.let {
CropImage.activity(uri)
.start(it, this)
Timber.d("enter album result ok uri:$uri")
}
}
Activity.RESULT_CANCELED ->{
Timber.d("Album_Result_Canceled")
}
}
}
REQUEST_FROM_CAMERA ->{
when(resultCode){
Activity.RESULT_OK->{
CropImage.activity(saveUri)
getContext()?.let {
CropImage.activity(saveUri)
.start(it,this)
}
}
Activity.RESULT_CANCELED->{
Timber.d("Camera_Result_Canceled")
}
}
}
}
}
}
在viewmodel 傳入 Path + Query方法 + MultipartBody.Part + Token
fun uploadImage(requestFile: MultipartBody.Part) {
val token = "Bearer " +_registerAccount.value?.token
viewModelScope.launch(Dispatchers.IO) {
val result = BookApi.retrofitService.apiUploadProfile(accountProfile.value?.user?.id.toString(),"PUT",requestFile,token).await()
if(result.isSuccessful){
Timber.d("upload成功")
}else{
try {
Timber.d("upload失敗errorbody ${result.errorBody()?.string()}")
}catch (e:IOException){
Timber.d("upload失敗e ${e.message}")
}
}
}
}
API interface
@Multipart
@POST("http://52.196.XXX/api/profile/{user_id}/photo")
@Headers("Content-Type: multipart/form-data")
fun apiUploadProfile(
@Path("user_id") userId: String,
@Query("_method") string: String,
@Part file: MultipartBody.Part,
@Header("authorization") token: String?
): Deferred<Response<ResponseBody>>
我在viewModel 印errorBody的時候出現
2021-06-05 20:46:08.490 4966-5205/com.example.solvingvoice D/MainViewModel$uploadImage: upload失敗errorbody <!doctype html>
其他的資訊
爬文之後,好像沒特別看到原因
這個問題卡了很久,我在想應該是MultiPart.Part格式的問題?
但也不確定是不是request請求方式有誤
想請教各位大大,可以怎麼解決,或是有可以參考的文章
不好意思敘述有點長,感謝!