iT邦幫忙

0

Android Kotlin 從首先相簿拿到 url之後無法上傳到 server使用 Retrofit

Tom 2021-06-05 21:12:49866 瀏覽

各位大大晚安

最近在練習取得相簿內照片,並且上傳到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>

其他的資訊
https://ithelp.ithome.com.tw/upload/images/20210605/20138017lR46X2Bp3B.jpg

爬文之後,好像沒特別看到原因
這個問題卡了很久,我在想應該是MultiPart.Part格式的問題?
但也不確定是不是request請求方式有誤
想請教各位大大,可以怎麼解決,或是有可以參考的文章
不好意思敘述有點長,感謝!

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友回答

立即登入回答