简体   繁体   中英

Okhttp3, FileNotFoundException on retrofit2 POST

As i'm showing a part of the code below, i'm trying to POST an image with retrofit2. Android Studio

I really can't understand what is the error, hope someone cud help me with this problem.

Imge service

import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part


interface ImageUploadService {

    @Multipart
    @POST("uploadfile")
    fun saveImage(
        @Part("description") description: RequestBody,
        @Part image: MultipartBody.Part
    ): Call<ResponseBody>
}

Imge request and retrofit init

import com.code.delegate.RequestDelegateOnSuccessFull
import com.code.retrofit.RetrofitInitialize
import com.code.retrofit.service.ImageUploadService
import com.softwareplace.workout.delegate.Delegate
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class ImageRequest(url: String) {

    private val service: ImageUploadService = RetrofitInitialize(url)
        .retrofit
        .create(ImageUploadService::class.java)

    fun postImageFile(delegate: Delegate<ResponseBody>, image: MultipartBody.Part, description: RequestBody) {
        service.saveImage(image = image, description = description).enqueue(object : Callback<ResponseBody> {
            override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                delegate.onFailure(t)
            }

            override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                RequestDelegateOnSuccessFull(response = response, delegate = delegate).run()
            }

        })
    }
}

Activity code

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.code.R
import com.code.retrofit.request.ImageRequest
import com.softwareplace.workout.delegate.Delegate
import com.softwareplace.workout.glide.GlideImageSet
import com.softwareplace.workout.ui.permission.PICK_FROM_GALLERY
import com.softwareplace.workout.ui.permission.Permission
import kotlinx.android.synthetic.main.activity_main.*
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.ResponseBody
import org.apache.commons.io.FileUtils
import java.io.File

class MainActivity : AppCompatActivity() {

    private lateinit var selectedImage: Uri

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        userSelectImageProfile()
        postImage()
    }

    private fun postImage() {
        user_register_button.setOnClickListener {

            if (selectedImage != null) {
                var descriptionBody = RequestBody.create(MultipartBody.FORM, "User Image")
                var image = FileUtils.getFile(File(selectedImage.path))

                var filePart = RequestBody.create(
                    MediaType.parse(contentResolver.getType(selectedImage)),
                    image
                )

                var imageFile = MultipartBody.Part.createFormData("file", image.name, filePart)

                ImageRequest(getString(R.string.base_url_file_upload)).postImageFile(
                    image = imageFile,
                    description = descriptionBody, delegate = object : Delegate<ResponseBody> {
                        override fun onSuccessFull(isSuccessFull: Boolean, response: ResponseBody?, message: String?) {
                            if (isSuccessFull) {
                                Log.i("ResponseBody", response.toString())
                            } else {
                                Log.i("ResponseError", message)
                            }
                        }

                        override fun onFailure(exception: Throwable) {
                            Log.i("Error", exception.message)
                            exception.printStackTrace()
                        }

                    })

            }
        }
    }

    private fun userSelectImageProfile() {
        user_image_select.setOnClickListener {
            Permission(this).getReadExternalStoragePemission()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Log.d("req", "req$requestCode")
        Log.d("res", "res$resultCode")

        if (requestCode == PICK_FROM_GALLERY && resultCode == RESULT_OK && null != data) {
            selectedImage = data.data
            val bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, selectedImage)
            GlideImageSet(context = this).glideImageSet(imageView = user_image_profile, data = bitmap)
        }
    }
}

When i try to POST this image file, i got this error

I/Error: /raw/storage/emulated/0/DCIM/Camera/IMG_20190109_141817_HDR.jpg (No such file or directory)
W/System.err: java.io.FileNotFoundException: /raw/storage/emulated/0/DCIM/Camera/IMG_20190109_141817_HDR.jpg (No such file or directory)
W/System.err:     at java.io.FileInputStream.open0(Native Method)
W/System.err:     at java.io.FileInputStream.open(FileInputStream.java:200)
        at java.io.FileInputStream.<init>(FileInputStream.java:150)
        at okio.Okio.source(Okio.java:168)
W/System.err:     at okhttp3.RequestBody$3.writeTo(RequestBody.java:119)
        at okhttp3.MultipartBody.writeOrCountBytes(MultipartBody.java:173)
W/System.err:     at okhttp3.MultipartBody.writeTo(MultipartBody.java:114)
        at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:72)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
W/System.err:     at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
W/System.err:     at okhttp3.RealCall$AsyncCall.execute(RealCall.java:200)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)

As you can see on the error message, No such file or directory, it looks like it can't find the file from the path.

I did many testes, so i got a solution as i will show in code below, but if you know a better solution, show me.

private fun postImage() {
    user_register_button.setOnClickListener {

        if (selectedImage != null) {
            var imageFile = File(baseContext.cacheDir, "${System.currentTimeMillis()}")
            imageFile.createNewFile()

            var arrayOutputStream = ByteArrayOutputStream()
            getBitmapFromUri(selectedImage).compress(Bitmap.CompressFormat.JPEG, 100, arrayOutputStream)
            var outputStream = FileOutputStream(imageFile)
            outputStream.write(arrayOutputStream.toByteArray())
            outputStream.flush()
            outputStream.close()


            var descriptionBody = RequestBody.create(MediaType.parse("image/*"), imageFile)
            val imagePart = MultipartBody.Part.createFormData("file", "${System.currentTimeMillis()}", descriptionBody)

            ImageRequest(getString(R.string.base_url_file_upload)).postImageFile(
                image = imagePart, delegate = object : Delegate<ResponseBody> {
                    override fun onSuccessFull(isSuccessFull: Boolean, response: ResponseBody?, message: String?) {
                        if (isSuccessFull) {
                            Log.i("ResponseBody", response.toString())
                        } else {
                            Log.i("ResponseError", message)
                        }
                    }

                    override fun onFailure(exception: Throwable) {
                        Log.i("Error", exception.message)
                        exception.printStackTrace()
                    }

                })

        }
    }
}

@Throws(IOException::class)
private fun getBitmapFromUri(uri: Uri): Bitmap {
    val parcelFileDescriptor = contentResolver.openFileDescriptor(uri, "r")
    val fileDescriptor = parcelFileDescriptor.fileDescriptor
    val image = BitmapFactory.decodeFileDescriptor(fileDescriptor)
    parcelFileDescriptor.close()
    return image
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM