Я создаю приложение Kotlin / Jvm (без Android Sdk), которое взаимодействует с экземпляром сервера Parse (Back4App). К сожалению, parse не предоставляет реализацию Sdk для использования с Java / Kotlin без Android.
Так что я использую остальные API. Сейчас я пытаюсь загрузить изображение с моего диска на файловый сервер Back4App. В doc есть фрагмент с использованием curl. Но я не смог перевести сервис Retrofit:
curl -X POST \
-H "X-Parse-Application-Id: 4MGgDJ0ZiQloXoSTE2I9VM6YUYIz8EwCKF4pK7zr" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: image/jpeg" \
--data-binary '@myPicture.jpg' \
https://YOUR.PARSE-SERVER.HERE/parse/files/pic.jpg
Итак, я основал свою реализацию в этой статье и других фрагментах из GitHub и создал для нее сервис модернизации:
@Multipart
@POST("/parse/files")
fun upload(
@Part file: MultipartBody.Part
): Call<ResponseBody>
И звоните:
var file = File("assets/escudo.png")
var requestFile = RequestBody.create(MediaType.parse("**/image"), file)
var body = MultipartBody.Part.createFormData("picture", file.name, requestFile)
var r = getService().upload(body).execute()
Я создал экземпляр модификации, как показано ниже:
fun getService(): ParserService {
val retrofit = Retrofit
.Builder()
.baseUrl("https://parseapi.back4app.com")
.addConverterFactory(GsonConverterFactory.create())
.client(createClient()).build()
return retrofit.create(ParserService::class.java)
}
fun createClient(): OkHttpClient {
return OkHttpClient.Builder().addInterceptor(createHeadInterceptor()).build()
}
fun createHeadInterceptor(): Interceptor {
return HeaderInterceptor()
}
class HeaderInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response =
chain.run {
val credentials = CredentialsUtils.readCredentials()
log.info { credentials }
proceed(
request().newBuilder()
// .addHeader("Content-Type", "application/json")
.addHeader("Content-Type", "image/png")
.addHeader("X-Parse-Application-Id", credentials.back4appAppId)
.addHeader("X-Parse-REST-API-Key", credentials.back4appRestApiKey)
.build()
)
}
}
Я смог использовать его для публикации данных Json (раскомментировав заголовок содержимого / типа). Но когда я попытался загрузить изображение, я получил этот ответ:
Response{protocol=h2, code=400, message=, url=https://parseapi.back4app.com/parse/files}
![enter image description here](https://i.stack.imgur.com/VA9mU.png)
Подробнее:
![enter image description here](https://i.stack.imgur.com/QGMhE.png)
- РЕДАКТИРОВАТЬ
Я пробовал другой подход без Retrofit, он дает код ответа 201 и дает мне objectId, но он не загружает файл:
val file2 = File("assets/escudo.png")
val serverUrl = "https://parseapi.back4app.com/classes/myfiles"
val url = URL(serverUrl)
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "POST"
conn.doOutput = true
val postData = file2.readBytes()
conn.addRequestProperty("Content-length", postData.size.toString())
conn.setRequestProperty("Content-Type", "image/*")
conn.setRequestProperty("X-Parse-Application-Id", credentials.back4appAppId)
conn.setRequestProperty("X-Parse-REST-API-Key", credentials.back4appRestApiKey)
val outputStream = DataOutputStream(conn.outputStream)
outputStream.write(postData)
outputStream.flush()
println(conn.responseCode)
![there should be a new column with the file, right?](https://i.stack.imgur.com/crZ2v.png)
- РЕДАКТИРОВАТЬ
Попробуем сейчас с помощью Khttp:
val file = File("assets/foto.jpg")
val file2 = File("assets/escudo.png")
val serverUrl = "https://parseapi.back4app.com/classes/myfiles"
val files = listOf(FileLike("foto.jpg", file), FileLike("escudo.png", file2))
val response = post(serverUrl, headers = getHeaders(), files = files)
println(response)
println(response.text)
}
fun getHeaders(): Map<String, String> {
return mapOf(
"Content-Type" to "image/*",
"X-Parse-Application-Id" to credentials.back4appAppId,
"X-Parse-REST-API-Key" to credentials.back4appRestApiKey
)
}
Получение этой ошибки:
<Response [400]>
{"error":"Unexpected token - in JSON at position 0"}