I want to upload image and some data to server. I'm using volley multipart request for that. While uploading the image I'm getting 500 error. I think its related to header part. API works fine in POSTMAN
If I request without boundary value I'm getting 400 error.any solution please provide.thanks in advance
private fun uploadImage() {
OFC_Utils.showProgressDialog(this, "", "")
val token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIwMGE1NzQxNC00M2JmLTQwYTEtODEyMS0zNWIzMTYyMGViZGIiLCJkZXZpY2VJZCI6IjVhNjYyMWQ5LTQwZTgtNGJlMC05MjQ4LWIzY2I2MDkzODdhZSIsImZhcm1JZCI6IiIsImxhbmd1YWdlIjoiRW5nbGlzaCIsInRpbWVab25lIjoiSW5kaWEgU3RhbmRhcmQgVGltZSIsInJvbGUiOiJQQVJBVkVURVJJTkFSSUFOIiwidmVyaWZpY2F0aW9uU3RhdHVzIjoiRmFsc2UiLCJuYmYiOjE2MTE4MTcxNzMsImV4cCI6MTYxMTgxODk3MywiaWF0IjoxNjExODE3MTczfQ.Eo8C6BRyY116JPJmVHEYMPcoZ1Rk2N_mEw4Hj-g4z8M"
val BOUNDARY = "--XX--" //This the boundary which is used by the server to split the post parameters.
val MULTIPART_FORMDATA = "multipart/form-data;boundary=$BOUNDARY"
imageData ?: return
val request = object : VolleyFileUploadRequest(
Method.POST,
Constants.Service_Urls.UPLOAD_FARM_DETAILS,
Response.Listener {
OFC_Utils.hideProgressDialog()
println("response is: $it")
},
Response.ErrorListener { error ->
var response = ""
OFC_Utils.hideProgressDialog()
val networkResponse = error.networkResponse
if (networkResponse != null && networkResponse.data != null) {
// val jsonError = String(networkResponse.data)
// val jsonobject:JSONObject= JSONObject(String(networkResponse.data))
Log.d("jsonerror", String(networkResponse.data))
// response=jsonobject.optString("status")
}
}
) {
override fun getByteData(): Map<String, Any>? {
val params = HashMap<String, FileDataPart>()
val imagename = System.currentTimeMillis()
params["ProfilePicFile"] = FileDataPart(imagename.toString(), imageData!!, "png")
return params
}
override fun getBodyContentType(): String {
return MULTIPART_FORMDATA
}
override fun getBody(): ByteArray {
val params = HashMap<String, String>()
params.put("CountryCode", "+91")
params.put("Phone", "1234567890")
params.put("Role", "PARAVET")
params.put("Name", "NAGS")
params.put("PreferredLanguage", "ENGLISH")
params.put("DeviceName", "REDMI6A")
params.put("DeviceType", "MOBILE")
params.put("Location", "banglore")
Log.d("params1", params.toString())
return params.toString().toByteArray()
}
override fun getHeaders(): MutableMap<String, String> {
val boundary = "apiclient-" + System.currentTimeMillis()
val headers = java.util.HashMap<String, String>()
Log.d("boundary", boundary.toString())
headers["Authorization"] = "bearer $token"
headers["Content-Type"] = MULTIPART_FORMDATA
return headers
}
}
Volley.newRequestQueue(this).add(request)
}
import android.util.Log
import com.android.volley.*
import com.android.volley.toolbox.HttpHeaderParser
import java.io.*
import kotlin.math.min
open class VolleyFileUploadRequest(
method: Int,
url: String,
listener: Response.Listener<NetworkResponse>,
errorListener: Response.ErrorListener) : Request<NetworkResponse>(method, url, errorListener) {
private var responseListener: Response.Listener<NetworkResponse>? = null
init {
this.responseListener = listener
}
private var headers: Map<String, String>? = null
private val divider: String = "--"
private val ending = "
"
//private val boundary = "apiclient-" + System.currentTimeMillis()
private val boundary = "--XX--"
override fun getHeaders(): MutableMap<String, String> =
when(headers) {
null -> super.getHeaders()
else -> headers!!.toMutableMap()
}
override fun getBodyContentType() = "multipart/form-data; boundary=" + boundary
@Throws(AuthFailureError::class)
override fun getBody(): ByteArray {
val byteArrayOutputStream = ByteArrayOutputStream()
val dataOutputStream = DataOutputStream(byteArrayOutputStream)
try {
if (params != null && params.isNotEmpty()) {
Log.d("params",params.toString())
processParams(dataOutputStream, params, paramsEncoding)
}
val data = getByteData() as? Map<String, FileDataPart>?
if (data != null && data.isNotEmpty()) {
processData(dataOutputStream, data)
}
dataOutputStream.writeBytes(divider + boundary + divider + ending)
return byteArrayOutputStream.toByteArray()
} catch (e: IOException) {
e.printStackTrace()
}
return super.getBody()
}
@Throws(AuthFailureError::class)
open fun getByteData(): Map<String, Any>? {
return null
}
override fun parseNetworkResponse(response: NetworkResponse): Response<NetworkResponse> {
return try {
Log.d("del_params",response.toString())
Response.success(response, HttpHeaderParser.parseCacheHeaders(response))
} catch (e: Exception) {
Response.error(ParseError(e))
}
}
override fun deliverResponse(response: NetworkResponse) {
responseListener?.onResponse(response)
Log.d("del_params",response.data.toString())
}
override fun deliverError(error: VolleyError) {
errorListener?.onErrorResponse(error)
// Log.d("error_params",error.message)
}
@Throws(IOException::class)
private fun processParams(dataOutputStream: DataOutputStream, params: Map<String, String>, encoding: String) {
try {
params.forEach {
dataOutputStream.writeBytes(divider + boundary + ending)
dataOutputStream.writeBytes("Content-Disposition: form-data; name="${it.key}"$ending")
dataOutputStream.writeBytes(ending)
dataOutputStream.writeBytes(it.value + ending)
}
} catch (e: UnsupportedEncodingException) {
throw RuntimeException("Unsupported encoding not supported: $encoding with error: ${e.message}", e)
}
}
@Throws(IOException::class)
private fun processData(dataOutputStream: DataOutputStream, data: Map<String, FileDataPart>) {
data.forEach {
val dataFile = it.value
dataOutputStream.writeBytes("$divider$boundary$ending")
dataOutputStream.writeBytes("Content-Disposition: form-data; name="${it.key}"; filename="${dataFile.fileName}"$ending")
if (dataFile.type != null && dataFile.type.trim().isNotEmpty()) {
dataOutputStream.writeBytes("Content-Type: ${dataFile.type}$ending")
}
dataOutputStream.writeBytes(ending)
val fileInputStream = ByteArrayInputStream(dataFile.data)
var bytesAvailable = fileInputStream.available()
val maxBufferSize = 1024 * 1024
var bufferSize = min(bytesAvailable, maxBufferSize)
val buffer = ByteArray(bufferSize)
var bytesRead = fileInputStream.read(buffer, 0, bufferSize)
while (bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize)
bytesAvailable = fileInputStream.available()
bufferSize = min(bytesAvailable, maxBufferSize)
bytesRead = fileInputStream.read(buffer, 0, bufferSize)
}
dataOutputStream.writeBytes(ending)
}
}
}
class FileDataPart(var fileName: String?, var data: ByteArray, var type: String)
question from:
https://stackoverflow.com/questions/65932535/getting-500-error-in-multipart-request-in-android-volley