微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

android 10 kotlin 改造的图像上传问题

如何解决android 10 kotlin 改造的图像上传问题

API 接口:

@Multipart
@POST(AppConstants.UPDATE_PRODUCT)
fun updateProduct(
    @Header("Authorization") auth: String,@Part("product_id") id: RequestBody,@Part("title") title: RequestBody,@Part("description") description: RequestBody,@Part("price") price: RequestBody,@Part image: MultipartBody.Part
) : Call<UpdateProductResponse>?

意图:

val photoIntent = Intent(Intent.ACTION_GET_CONTENT).apply {
                    type = "image/*"
                    addCategory(Intent.CATEGORY_OPENABLE)
                }
                startActivityForResult(photoIntent,UPLOAD_IMAGE)

活动结果:

override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
    super.onActivityResult(requestCode,resultCode,data)
    if (requestCode == UPLOAD_IMAGE && resultCode == RESULT_OK) {
        if (data != null) {
            val bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver,data.data)
            update_iv.setimageBitmap(bitmap)

            val imageType = contentResolver.getType(data.data!!)
            val extension = imageType!!.substring(imageType.indexOf("/") + 1)

            val file = File(getPath(data.data!!,this)!!)
            
            //val byte = contentResolver.openInputStream(data.data!!)
            //val contentPart = InputStreamRequestBody("image/*".toMediaType(),contentResolver,data.data!!)

            //filePartimage = MultipartBody.Part.createFormData("image",file.name,contentPart)
            data.data!!.let {
                application.contentResolver.openInputStream(it)?.use { inputStream ->
                    filePartimage = MultipartBody.Part.createFormData(
                        "image","" + file.name,//or "image.$extension" none of the two works
                        inputStream.readBytes().toRequestBody("image/*".toMediaType())
                    )
                }
            }
            showMessage(this,"" + getString(R.string.image_uploaded))
        } else {
            showMessage(this,"" + "File upload Failed!")
        }
    }
}

API 调用: 这里 filePartimage 是这样的全局变量:private var filePartimage: MultipartBody.Part? = 空

    RetrofitClientInstance().createService(ArtOFiestaServiceClass::class.java).updateProduct(
        "Bearer " + Prefs.getString("token",""),id.trim().toRequestBody("text/plain".toMediaType()),update_name.text.toString().trim().toRequestBody("text/plain".toMediaType()),update_desc.text.toString().trim().toRequestBody("text/plain".toMediaType()),update_price.text.toString().trim().toRequestBody("text/plain".toMediaType()),filePartimage!!
    )?.enqueue(object : retrofit2.Callback<UpdateProductResponse> {
        override fun onResponse(
            call: Call<UpdateProductResponse>,response: Response<UpdateProductResponse>
        )

清单:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
android:requestLegacyExternalStorage="true"

我在 node js 中开发了它的后端,并使用 multer 上传文件。我可以使用邮递员上传文件,但无法通过我的移动应用程序上传。我的代码有什么问题?可能是 android Scoped Storage 问题吗?

解决方法

问题是由于Scoped Storage,因为我也面临同样的问题。

我的解决方案是将 inputStream 转换为相同的 File 并将其存储在其他地方。然后上传后,您可以删除该文件。

想法如下。

contentResolver.openInputStream(it)?.use { inputStream ->
    // STEP 1: Create a tempFile for storing the image from scoped storage. 
    val tempFile = createTempFile(this,fileName,extension)

    // STEP 2: copy inputStream into the tempFile
    copyStreamToFile(it,tempFile)

    // STEP 3: get file path from tempFile for further upload process. 
    val filePath = tempFile.absolutePath

    val requestFile: RequestBody = File(filePath).asRequestBody(fileType?.toMediaTypeOrNull())
    val body: MultipartBody.Part = MultipartBody.Part.createFormData("file",requestFile)
}
@Throws(IOException::class)
fun createTempFile(context: Context,fileName: String?,extension: String?): File {
    val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
    return File(storageDir,"$fileName.$extension")
}

fun copyStreamToFile(inputStream: InputStream,outputFile: File) {
    inputStream.use { input ->
        val outputStream = FileOutputStream(outputFile)
        outputStream.use { output ->
            val buffer = ByteArray(4 * 1024) // buffer size
            while (true) {
                val byteCount = input.read(buffer)
                if (byteCount < 0) break
                output.write(buffer,byteCount)
            }
            output.flush()
        }
    }
 }
,

.toRequestBody("image/*".toMediaType()) 替换为 .toRequestBody(imageType.toMediaTypeOrNull) 完成了工作

if (requestCode == UPLOAD_IMAGE && resultCode == RESULT_OK) {
        if (data != null) {
            val bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver,data.data)
            update_iv.setImageBitmap(bitmap)

            val imageType = contentResolver.getType(data.data!!)
            val extension = imageType!!.substring(imageType.indexOf("/") + 1)

            val file = File(getPath(data.data!!,this)!!)

            data.data!!.let {
                application.contentResolver.openInputStream(it).use { inputStream ->
                    filePartImage = MultipartBody.Part.createFormData(
                        "image",file.name,inputStream!!.readBytes().toRequestBody(imageType.toMediaTypeOrNull())
                    )
                }
            }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。