Я был бы очень признателен за помощь в решении этой проблемы.
Я пытаюсь опубликовать изображение в API синтаксического анализа квитанции и у меня возникают проблемы при создании фактического запроса.
Я прочитал и использовал большую часть кода этой статьи , написанной tarek на Medium, для создания класса MultiPart (с https), например:
Multipart.kt
package com.example.skopal.foodme.services
import java.io.BufferedReader
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStream
import java.io.OutputStreamWriter
import java.io.PrintWriter
import java.net.URL
import javax.net.ssl.HttpsURLConnection
class Multipart
/**
* This constructor initializes a new HTTPS POST request with content type
* is set to multipart/form-data
* @param url
* *
* @throws IOException
*/
@Throws(IOException::class)
constructor(url: URL) {
companion object {
private val LINE_FEED = "\r\n"
private val maxBufferSize = 1024 * 1024
private val charset = "UTF-8"
}
// creates a unique boundary based on time stamp
private val boundary: String = "===" + System.currentTimeMillis() + "==="
private val httpsConnection: HttpsURLConnection = url.openConnection() as HttpsURLConnection
private val outputStream: OutputStream
private val writer: PrintWriter
init {
httpsConnection.setRequestProperty("Accept-Charset", "UTF-8")
httpsConnection.setRequestProperty("Connection", "Keep-Alive")
httpsConnection.setRequestProperty("Cache-Control", "no-cache")
httpsConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary)
httpsConnection.setChunkedStreamingMode(maxBufferSize)
httpsConnection.doInput = true
httpsConnection.doOutput = true // indicates POST method
httpsConnection.useCaches = false
outputStream = httpsConnection.outputStream
writer = PrintWriter(OutputStreamWriter(outputStream, charset), true)
}
/**
* Adds a upload file section to the request
* @param fieldName - name attribute in <input type="file" name="..."></input>
* *
* @param uploadFile - a File to be uploaded
* *
* @throws IOException
*/
@Throws(IOException::class)
fun addFilePart(fieldName: String, uploadFile: File, fileName: String, fileType: String) {
writer.append("--").append(boundary).append(LINE_FEED)
writer.append("Content-Disposition: file; name=\"").append(fieldName)
.append("\"; filename=\"").append(fileName).append("\"").append(LINE_FEED)
writer.append("Content-Type: ").append(fileType).append(LINE_FEED)
writer.append(LINE_FEED)
writer.flush()
val inputStream = FileInputStream(uploadFile)
inputStream.copyTo(outputStream, maxBufferSize)
outputStream.flush()
inputStream.close()
writer.append(LINE_FEED)
writer.flush()
}
/**
* Adds a header field to the request.
* @param name - name of the header field
* *
* @param value - value of the header field
*/
fun addHeaderField(name: String, value: String) {
writer.append("$name: $value").append(LINE_FEED)
writer.flush()
}
/**
* Upload the file and receive a response from the server.
* @param onSuccess
* *
* @param onFailure
* *
* @throws IOException
*/
@Throws(IOException::class)
fun upload(onSuccess: (String) -> Unit, onFailure: ((Int) -> Unit)? = null) {
writer.append(LINE_FEED).flush()
writer.append("--").append(boundary).append("--")
.append(LINE_FEED)
writer.close()
try {
// checks server's status code first
val status = httpsConnection.responseCode
if (status == HttpsURLConnection.HTTP_OK) {
val reader = BufferedReader(InputStreamReader(httpsConnection.inputStream))
val response = reader.use(BufferedReader::readText)
httpsConnection.disconnect()
onSuccess(response)
} else {
onFailure?.invoke(status)
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
И я звоню вышеупомянутому классу из:
ReceiptRecognitionApi.kt
fun parseReceipt(file: File, cb: (String) -> Unit) {
println("parseReceipt_1")
Thread {
val multipartReq = Multipart(URL(baseUrl))
multipartReq.addHeaderField("apikey", taggunApiKey)
multipartReq.addHeaderField("Accept", "application/json")
multipartReq.addFilePart("file", file, "receipt.jpg", "image/jpeg")
multipartReq.upload(
onSuccess = { response: String ->
cb(response)
},
onFailure = { responseCode: Int ->
cb("$responseCode")
})
}.start()
}
Проблема в том, что после инициализации объекта Multipart я не могу добавить к нему какие-либо заголовки или данные. Например. если два addHeaderField
-коллока в вызове функции parseReceipt
перемещены в init
-блок в Multipart.kt , заголовки находятся в запросе, но в противном случае - нет.
Что я здесь не так делаю?