Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
251 views
in Technique[技术] by (71.8m points)

kotlin - Getting 500 error in multipart request in android volley

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

500 means server error. If it works fine on Postman but not on your app it means you are not sending the request properly in your app but you do in Postman. It can be because of the data you're trying to send or any other thing. Try sending the same data you are sending via Postman or using the same headers etc.

But since 500 means server error, you can just ask the backend developer to tell you what is the exact error so you can fix it easily.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...