1

FILE 是使用 cacheDir 中的 URI 创建的,但是当我尝试获取路径时,找不到图像,在创建文件之前记录了 URI,并且能够看到图像文件的正确 URI。现在我在应用程序缓存中创建了一个文件并尝试检索图像的路径然后没有获得完整的图像路径,不确定图像是否创建这是我的代码

 val imagesList = data?.extras?.getStringArray(GligarPicker.IMAGES_RESULT)
                if (!imagesList.isNullOrEmpty()) {
                    val arrayList = ArrayList<MultipartBody.Part>()
                    for (i in 0 until imagesList.size) {
                        Log.e("imagesList.item", imagesList[i])
                        val uri = Uri.parse("file://" + imagesList[i].toString())
                        Log.e("URI", uri.toString())
                        val parcelFileDescriptor: ParcelFileDescriptor? =
                            requireContext().contentResolver.openFileDescriptor(uri, "r")
                        val fileDescriptor: FileDescriptor? = parcelFileDescriptor?.fileDescriptor

                        val file = File(
                            requireContext().cacheDir,
                            requireContext().contentResolver.getFileName(uri!!)
                        )
                        Log.e("File", file.path.toString())

                        val inputStream = FileInputStream(fileDescriptor)
                        val outputStream = FileOutputStream(file)
                        inputStream.copyTo(outputStream)

                        // creates RequestBody instance from file

                        val requestFile: RequestBody =
                            RequestBody.create("multipart/form-data".toMediaTypeOrNull(), file)
                        // requireContext().create("multipart/form-data".toMediaTypeOrNull(), file)

                        val body: MultipartBody.Part? =
                            MultipartBody.Part.createFormData("image", file.name, requestFile)

                        if (body != null) {
                            arrayList.add(body)
                        }
                    }

尝试记录 URI 和 FILEPATH ,这是详细信息

URI: file:///storage/emulated/0/DCIM/Camera/IMG_20210131_150237.jpg
File: /data/user/0/com.visilogix.smarttrax/cache

错误日志

  Caused by: java.io.FileNotFoundException: /data/user/0/com.visilogix.smarttrax/cache: open failed: EISDIR (Is a directory)
    at libcore.io.IoBridge.open(IoBridge.java:496)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
    at com.visilogix.smarttrax.ui.performPutAway.GrnLinesFragment.onActivityResult(GrnLinesFragment.kt:283)
    at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
    at android.app.Activity.dispatchActivityResult(Activity.java:8110)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4838)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4886) 
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
 Caused by: android.system.ErrnoException: open failed: EISDIR (Is a directory)
    at libcore.io.Linux.open(Native Method)

更新了创建文件的代码

  val uri = Uri.parse("file://" + imagesList[i].toString())
                    Log.e("URI", uri.toString())
                    val parcelFileDescriptor: ParcelFileDescriptor? =
                        requireContext().contentResolver.openFileDescriptor(uri, "r")
                    val fileDescriptor: FileDescriptor? = parcelFileDescriptor?.fileDescriptor

                    val uri1 = Uri.parse(imagesList[i].toString())
                    Log.e("File", requireContext().contentResolver.getFileName(uri1!!))
                    val file = File(
                        requireContext().externalCacheDir?.path,
                        requireContext().contentResolver.getFileName(uri1!!)
                    )
                    file.parentFile.mkdir()
                    file.createNewFile()
                    Log.e(
                        "File2",
                        requireContext().contentResolver.getFileName(uri1!!).toString()
                    )

                    val inputStream = FileInputStream(fileDescriptor)
                    val outputStream = FileOutputStream(file)
                    inputStream.copyTo(outputStream)

应用程序在崩溃val outputStream = FileOutputStream(file)

 Caused by: java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.visilogix.smarttrax/cache: open failed: EISDIR (Is a directory)
    at libcore.io.IoBridge.open(IoBridge.java:496)
4

2 回答 2

1

在创建文件时使用“externalCacheDir”而不是“cacheDir”可能会解决问题。

requireContext().externalCacheDir?.let {
            val file = File(
                    it.path,
                    requireContext().contentResolver.getFileName(uri!!)
            )
            file.createNewFile()

        }
于 2021-02-27T06:09:10.007 回答
1

使用 Okhttp 将图像发送到 php 服务器:首先将所有图像转换为字节数组并将其放入“backupData”列表中。然后调用“backupOneByOne()”方法。

private var client: OkHttpClient = OkHttpClient()

init {
    client.setReadTimeout(5, TimeUnit.MINUTES)
    client.setConnectTimeout(5, TimeUnit.MINUTES)
}
val backupData: MutableList<ByteArray> = mutableListOf()

private suspend fun backupOneByOne(currentPosition: Int, byteArray: ByteArray) {
    val backupResponse = doBackupMultiPartData("merchantKey", byteArray)

    when (backupResponse) {
        is ResponseResult.Success -> {
            Log.d("nm==>>", "Menu Item backup successful !!! AND current item position= $currentPosition")
            if (currentPosition < backupData.size - 1) {
                backupOneByOne(currentPosition + 1, backupData[currentPosition + 1])
            } else {
                Log.d("nm==>>", "Backup of all items is done. Current position= $currentPosition")
            }
        }
        is ResponseResult.Error -> {
            Log.d("nm==>>", "Error while backup of Advance table : \n ${backupResponse.msg.errorMsg}")
        }
        else -> {
        }
    }
}
suspend fun doBackupMultiPartData(apiKey: String, imageData: ByteArray?): ResponseResult<ResponseWrapper<String>> {
    val requestBody = MultipartBuilder().type(MultipartBuilder.FORM)
    //requestBody.addFormDataPart("id",2) put other form data fields
    if (imageData != null) {
        requestBody.addFormDataPart(
                "file", "Logo.png", RequestBody.create(
                MediaType.parse(
                        "image/png"
                ), imageData
        )
        )
    }

    val request = Request.Builder()
            .header("api_key", apiKey) // getting api key from backend
            .url("put url here....")
            .post(requestBody.build())
            .build()
    try {
        val result = apiRequest(request)
        Log.d("nm==>>", "Result: $result")
        return if (result != null) {
            val jsonObject = JSONObject(result)
            if (jsonObject.getBoolean("isSuccessful")) {
                ResponseResult.Success(ResponseWrapper("success", null))
            } else {
                ResponseResult.Error(
                        ResponseWrapper(null, "Back end code error: \n $result")
                )
            }
        } else {
            ResponseResult.Error(
                    ResponseWrapper(
                            null, "Getting NULL as result"
                    )
            )
        }
    } catch (jsonException: JSONException) {
        Log.d("nm==>>", "Restore JSON exception::: \n ${jsonException.localizedMessage}")
        return ResponseResult.Error(
                ResponseWrapper(
                        null,
                        "Restore Json Exception"
                )
        )
    } catch (exception: Throwable) {
        //Log.d("nm==>>", "Network exception::: \n ${exception.localizedMessage}")
        return ResponseResult.NoInternet
    }
}

private suspend fun apiRequest(request: Request): String? = suspendCancellableCoroutine { cancellableContinuation ->
    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(request: Request?, e: IOException?) {
            cancellableContinuation.resumeWith(Result.failure(Throwable("API failed.....${e?.localizedMessage}")))
        }

        override fun onResponse(response: Response?) {
            cancellableContinuation.resumeWith(Result.success(response?.body()?.string()))
        }
    })
}
sealed class ResponseResult<out T> {
    object Loading:ResponseResult<Nothing>()
    object Empty:ResponseResult<Nothing>()
    data class Success<T>(val result:T): ResponseResult<T>()
    data class Error<T>(val msg:T): ResponseResult<T>()
    object NoInternet:ResponseResult<Nothing>()
}
data class ResponseWrapper<out T>(val data: T?, val errorMsg: String?)
于 2021-02-27T08:30:37.233 回答