Я сделал многокомпонентный запрос на сервер для отправки изображений из телефонной галереи в соответствии с руководством, но я не знаю, что с ним не так.Сервер вернет код ответа 201, но изображение отправлено на сервер неправильно.
Вот функция HTTPRequest для отправки изображения.
fun doPostImage(resources: String, avatarImage: ByteArray, fileName: String): JSONObject{
val url = SERVER_URL + resources
val maxBufferSize = 1024 * 1024
val X_SESSION: String? = context?.getSharedPreferences(context.
getString(R.string.SharedPrefs), MODE_PRIVATE)?.
getString(context.getString(R.string.X_SESSION), null)
createLog("AvatarRequestURL", "POST $url")
val obj = URL(url)
val attachmentName = fileName
val attachmentFileName = fileName + ".jpg"
val crlf = "\r\n"
val twoHyphens = "--"
val boundary = "*****"
with(obj.openConnection() as HttpURLConnection) {
requestMethod = "POST"
doOutput = true
doInput = true
val postData: ByteArray = avatarImage
if (X_SESSION != null){
createLog("DOPOST-SESSION", X_SESSION)
setRequestProperty("X-Session", X_SESSION)
} else {
createLog("DOPOST-SESSION", "SESSION NULL :(")
}
setRequestProperty("Connection", "Keep-Alive")
setRequestProperty("Cache-Control", "no-cache")
setRequestProperty("X-API-Key", API_KEY)
setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary)
setChunkedStreamingMode(maxBufferSize)
//constructing request body
try {
val writer = PrintWriter(OutputStreamWriter(outputStream, "UTF-8"), true)
writer.append(twoHyphens + boundary + crlf)
writer.append("Content-Disposition: form-data; name=\"" + attachmentName + "\";filename=\"" + attachmentFileName + "\"" + crlf)
writer.append("Content-Type", "image/jpeg")
writer.append(crlf)
writer.flush()
val byteArrayInputStream = ByteArrayInputStream(postData)
byteArrayInputStream.copyTo(outputStream, maxBufferSize)
} catch (exception: Exception) {
createLog("AvatarImageException", exception.toString())
}
createLog("Avatar_Upload_Response", "Response Code Image: $responseCode")
//server response handling
if (responseCode != HttpURLConnection.HTTP_OK) {
try {
BufferedReader(InputStreamReader(errorStream)).use {
val response = StringBuffer()
var inputLine = it.readLine()
while (inputLine != null) {
response.append(inputLine)
inputLine = it.readLine()
}
createLog("AvatarRequest", "Response body Image: $response")
return JSONObject(response.toString())
}
} catch (exception: Exception) {
return if(responseCode == HttpURLConnection.HTTP_CLIENT_TIMEOUT){
createLog("POST EXCEPTION", exception.toString())
val errorResponse = JSONObject()
errorResponse.put("ErrorCode", responseCode)
errorResponse.put("Message", exception.message)
errorResponse
} else {
createLog("EXCEPTION", exception.toString())
val errorResponse = JSONObject()
errorResponse.put("ErrorCode", responseCode)
errorResponse.put("Message", exception.message)
return errorResponse
}
}
} else {
try {
BufferedReader(InputStreamReader(inputStream)).use {
val response = StringBuffer()
var inputLine = it.readLine()
while (inputLine != null) {
response.append(inputLine)
inputLine = it.readLine()
}
createLog("AvatarRequest", "Response body Image: $response")
return JSONObject(response.toString())
}
} catch (exception: Exception) {
throw Exception("Exception while push the notification $exception")
}
}
}
}
Вот как я получаю изображение из галереи:
profilePhotoSelectButton.setOnClickListener {
val galleryIntent = Intent()
galleryIntent.type = "image/*"
galleryIntent.action = Intent.ACTION_GET_CONTENT
startActivityForResult(Intent.createChooser(galleryIntent, "Choose profile photo"), PICK_PHOTO)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == PICK_PHOTO){
val avatarPhoto: Uri? = data?.data
if (avatarPhoto != null){
val imageStream: InputStream = contentResolver.openInputStream(avatarPhoto)
val imageBitmap: Bitmap = BitmapFactory.decodeStream(imageStream)
val roundedBitMapDrawable: RoundedBitmapDrawable = RoundedBitmapDrawableFactory.create(resources, imageBitmap)
roundedBitMapDrawable.isCircular = true
profilePhotoPreview.setImageDrawable(roundedBitMapDrawable)
val userPhotoToJSON: Bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, avatarPhoto)
val resizedBitmap: Bitmap = getResizedBitmap(userPhotoToJSON, 150)
userProfilePhotoEncoded = compressBitmap(resizedBitmap, Bitmap.CompressFormat.JPEG)
userProfilePhotoPath = avatarPhoto.path
createLog("AvatarPath ", userProfilePhotoPath.toString())
userProfilePhotoName = File(avatarPhoto.path).name
createLog("AvatarName ", userProfilePhotoName.toString())
}
}
}
private fun compressBitmap(bitmapPicture: Bitmap, compressFormat: Bitmap.CompressFormat): ByteArray {
val COMPRESSION_QUALITY = 50
val byteArrayBitmapStream = ByteArrayOutputStream()
bitmapPicture.compress(compressFormat, COMPRESSION_QUALITY, byteArrayBitmapStream)
val avatarByteArray: ByteArray = byteArrayBitmapStream.toByteArray()
return avatarByteArray
}
/**
* reduces the size of the image
* @param image
* @param maxSize
* @return
*/
fun getResizedBitmap(image: Bitmap, maxSize: Int): Bitmap {
var width = image.width
var height = image.height
val bitmapRatio = width.toFloat() / height.toFloat()
if (bitmapRatio > 1) {
width = maxSize
height = (width / bitmapRatio).toInt()
} else {
height = maxSize
width = (height * bitmapRatio).toInt()
}
return Bitmap.createScaledBitmap(image, width, height, true)
}
api.updateAvatar(userProfilePhotoEncoded!!,userProfilePhotoPath!!, userProfilePhotoName!!, object: IProfileCallback{
override fun onError(errorJSON: JSONObject) {
createLog("AVATAR_ERROR ", errorJSON.toString())
}
override fun onSuccess(profileJSON: JSONObject?) {
createLog("AVATAR SUCCESS", profileJSON.toString())
setResult(MYDATA_UPDATE_RESULT)
finish()
}
})
fun updateAvatar(avatar: ByteArray, filepath: String, fileName: String, callback: IProfileCallback){
class UpdateProfileAsync(private val profileCallback: IProfileCallback): AsyncTask<Void, Void, JSONObject>() {
override fun doInBackground(vararg p0: Void?): JSONObject {
val server = Server.getInstance(context!!)
return server.doPostImage(context.getString(R.string.profile_avatar_link), avatar, fileName)
}
override fun onPostExecute(result: JSONObject?) {
super.onPostExecute(result)
if(result!!.has("ErrorCode")){
profileCallback.onError(result)
} else {
createLog("SuccessfullyUpdatedProfile", "onSuccess()")
profileCallback.onSuccess(result)
}
}
}
UpdateProfileAsync(callback).execute()
}