【发布时间】:2022-08-13 21:06:13
【问题描述】:
使用文件作为源上传到 S3 签名的 URL 没有问题,但是尝试使用从 ActivityResult 获得的 Uri 对我不起作用。
这是我尝试的:
我正在使用 InputStreamRequestBody 类,如下所述:https://commonsware.com/blog/2020/07/05/multipart-upload-okttp-uri.html
class InputStreamRequestBody(
private val contentType: MediaType,
private val contentResolver: ContentResolver,
private val uri: Uri
) : RequestBody() {
override fun contentType() = contentType
override fun contentLength(): Long = -1
@Throws(IOException::class)
override fun writeTo(sink: BufferedSink) {
val input = contentResolver.openInputStream(uri)
input?.use { sink.writeAll(it.source()) }
?: throw IOException(\"Could not open $uri\")
}
}
我的改造 UploadAPI 接口:
interface UploadAPI {
@PUT
suspend fun uploadFile(
@Header(\"x-amz-acl\") contentType: String,
@Url uploadUrl: String,
@Body file: RequestBody
): Response<Unit>
companion object {
const val BASE_URL = \"https://....com\"
}
}
这里是我在 AppModule 中的改造单例:
@Provides
@Singleton
fun provideUploadApi(): UploadAPI {
return Retrofit.Builder()
.baseUrl(UploadAPI.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(UploadAPI::class.java)
}
然后使用我的 Uri(在我的存储库中)调用 InputStreamRequestBody 类并调用改造实例和上传函数:
val resolver = context.contentResolver
val type = (\"image/jpeg\").toMediaType()
val contentPart = InputStreamRequestBody(type, resolver, content)
uploadAPI.uploadFile(
\"public-read\",
mySignedUrl,
contentPart
)
这是我的 logginInterceptor 告诉我的:
2022-05-19 22:16:48.844 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: --> PUT https://app-content.ams3.digitaloceanspaces.com/Files/Test/profilbild.webp?Content-Type=image%2Fwebp&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=CENSORED-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read
2022-05-19 22:16:48.844 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: Content-Type: image/jpeg
2022-05-19 22:16:48.844 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: x-amz-acl: public-read
2022-05-19 22:16:48.896 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: --> END PUT (binary -1-byte body omitted)
2022-05-19 22:16:49.503 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: <-- 411 Length Required https://app-content.ams3.digitaloceanspaces.com/Files/Test/profilbild.webp?Content-Type=image%2Fwebp&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=CENSORED-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read (606ms)
2022-05-19 22:16:49.504 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: content-length: 239
2022-05-19 22:16:49.504 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: x-amz-request-id: tx000000000000004541b27-00622f61-20f93ecc-ams3c
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: accept-ranges: bytes
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: content-type: application/xml
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: date: Thu, 19 May 2022 15:16:49 GMT
2022-05-19 22:16:49.505 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: cache-control: max-age=60
2022-05-19 22:16:49.506 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: strict-transport-security: max-age=15552000; includeSubDomains; preload
2022-05-19 22:16:49.506 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: connection: close
2022-05-19 22:16:49.506 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: <?xml version=\"1.0\" encoding=\"UTF-8\"?><Error><Code>MissingContentLength</Code><BucketName>app-content</BucketName><RequestId>tx00000000000000fffb27-0062865f61-20f93ecc-ams3c</RequestId><HostId>20f93ecc-ams3c-ams3-zg03</HostId></Error>
2022-05-19 22:16:49.507 8469-8703/com.havanasun.loginplayground I/okhttp.OkHttpClient: <-- END HTTP (239-byte body)
我有强烈的感觉,我不能只将 InputStreamRequestBody 的实例作为 requestBody 传递,即使这个类继承自 RequestBody。
标签: android kotlin file-upload retrofit2 okhttp