如何修复kotlin中FileInputStream和FileDescriptor的错误路径



文件是在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)

使用" externalCacheDir"而不是"cacheDir"而创建文件可能会解决这个问题。

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

使用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?)