首页 > 解决方案 > 在使用 Retrofit2 上传到服务器之前调整图像文件的大小

问题描述

我正在尝试使用 Retrofit 将图像上传到服务器,但现在我面临图像尺寸太大的问题。这是我的代码:

private fun uploadImageFileToApiServer(){
    Log.e("api", "start")
    var file: File?= null
    try{

        file = File(Common.getFilePath(this, selectedUri!!))
        Log.e("FilePath", file.toString())

    }catch(e: URISyntaxException) {e.printStackTrace()}


    if(file != null)
    {
        val requestBody = ProgressRequestBody(file, this)

        //how can i resize the image here before uploading it to server???


        val body = MultipartBody.Part.createFormData("image", file.name, requestBody)
        Thread(Runnable {
            mService.uploadFile(body) 
                .enqueue(object: Callback<String> {
                    override fun onFailure(call: Call<String>, t: Throwable) {
                        Toast.makeText(this@ApiProcessing, t.message, Toast.LENGTH_LONG).show()
                        Log.e("api", t.message!!)
                    }

                    override fun onResponse(call: Call<String>, response: Response<String>) {
                        val stringResponse = response.body()?.toString()

                        try {
                            val jsonObject = JSONObject(stringResponse)
                            val label = jsonObject.getString("label")
                            val width = jsonObject.getString("width")
                            val height = jsonObject.getString("height")
                            HaveFruitResult.label = label
                            HaveFruitResult.width = width
                            HaveFruitResult.height = height
                 
                        }
                        catch (e: NullPointerException){
                            Toast.makeText(this@ApiProcessing, e.message, Toast.LENGTH_LONG).show()
                            //moveToMainActivity()
                            val handler = Handler()
                            handler.postDelayed({
                                moveToMainActivity()
                            }, 4000)
                        }
                    }
                })

        }).start()
    }
    else
    {
        Toast.makeText(this@ApiProcessing, "Fail!!", Toast.LENGTH_LONG).show()
    }
    Log.e("api", "end")
}

因为图片太大,上传需要很长时间,所以有时我无法从 API 服务器取回响应。这是我的 IUploadAPI

interface IUploadAPI {
@Multipart
@POST("/fruit_vision_api")
fun uploadFile(@Part file: MultipartBody.Part) : Call<String>
}

我怎么解决这个问题?非常感谢您的帮助!!!!!!!!!

标签: androidkotlinretrofit2

解决方案


我正在使用这个对象将图像压缩到最大 1Mo。您可以使用它或根据需要进行调整

/**
 * Definition of the BitmapUtils object.
 */
object BitmapUtils {
    const val ONE_KO = 1024
    const val ONE_MO = ONE_KO * ONE_KO

    /**
     * Compress, if needed, an image file to be lower than or equal to 1 Mo
     *
     * @param filePath Image file path
     *
     * @return Stream containing data of the compressed image. Can be null
     */
    fun compressedImageFile(filePath: String): InputStream? {
        var quality = 100
        var inputStream: InputStream? = null
        if (filePath.isNotEmpty()) {
            var bufferSize = Integer.MAX_VALUE
            val byteArrayOutputStream = ByteArrayOutputStream()
            try {
                val bitmap = BitmapFactory.decodeFile(filePath)
                do {
                    if (bitmap != null) {
                        byteArrayOutputStream.reset()
                        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream)
                        bufferSize = byteArrayOutputStream.size()
                        logD { "quality: $quality -> length: $bufferSize" }
                        quality -= 10
                    }
                } while (bufferSize > ONE_MO)
                inputStream = ByteArrayInputStream(byteArrayOutputStream.toByteArray())
                byteArrayOutputStream.close()
            } catch (e: Exception) {
                logE { "Exception when compressing file image: ${e.message}" }
            }
        }
        return inputStream
    }
}

要从 InputStream 创建文件,您可以使用以下扩展名:

fun File.copyInputStreamToFile(inputStream: InputStream) {
    this.outputStream().use { fileOut ->
        inputStream.copyTo(fileOut)
    }
}

并使用它:

var file = File(YOUR_PATH)
file.copyInputStreamToFile(BitmapUtil.compressedImageFile(filePath))

推荐阅读