Reputation: 469
I'm trying to uploading image to server using Retrofit, but now i'm facing a problem that the image's size is too large. Here is my code:
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")
}
Because the image's size is too large and it takes a lot of time to be uploaded so sometimes i cant get back the responses from API server. Here is my IUploadAPI
interface IUploadAPI {
@Multipart
@POST("/fruit_vision_api")
fun uploadFile(@Part file: MultipartBody.Part) : Call<String>
}
How can i solve this problem? Thanks very much for your help!!!!!!!!!
Upvotes: 1
Views: 1594
Reputation: 4007
I'm using this object to compress an image to 1Mo max. You can use it or adjust it to your needs
/**
* 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
}
}
To create a file from the InputStream, you can use this extension:
fun File.copyInputStreamToFile(inputStream: InputStream) {
this.outputStream().use { fileOut ->
inputStream.copyTo(fileOut)
}
}
And to use it:
var file = File(YOUR_PATH)
file.copyInputStreamToFile(BitmapUtil.compressedImageFile(filePath))
Upvotes: 1