【发布时间】:2019-03-10 02:13:02
【问题描述】:
我正在创建一个与 Parse Server (Back4App) 实例交互的 Kotlin/Jvm(没有 Android Sdk)应用程序。不幸的是,parse 没有提供在没有 Android 的情况下与 Java/Kotlin 一起使用的 SDK 实现。
所以我正在使用其余的 Api。现在我尝试将图像从我的磁盘上传到 Back4App 文件服务器。在doc 中有使用 curl 的 sn-p。但我无法翻译成改造服务:
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
所以我将我的实现基于这个article 和来自 GitHub 的其他 sn-ps,并为它创建了一个改造服务:
@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}
更多信息:
-- 编辑
我在没有 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)
-- 编辑
现在正在尝试使用 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"}
【问题讨论】:
-
疯狂猜测...尝试在 POST 中执行 byteArray 主体(不要使用 mime multipart),如这里的答案:stackoverflow.com/questions/49188722/…
-
我试图在那个答案中剪断它,它提供了一个 http 200 代码,但它没有上传文件。我想我错过了什么......
-
响应正文中有什么内容?它是否与对象上的 POST 的 parse.rest.docs 匹配?响应应包括 OID 和日期/时间戳...检查文档
-
我已经编辑了提供更多信息的问题。是的,当它用 http 200 回答时,它会用这个 json 回答:[text={"objectId":"YLWzWbaMjq","createdAt":"2019-03-10T21:00:25.171Z"}]。但它与文档不匹配。响应应包含指向已上传文件的链接。
-
gist.github.com/cmcdonaldca/5668086?#file-parsetest-java-L32 你使用了不正确的 url 来解析 rest 上传。
标签: rest http kotlin parse-server back4app