添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

PUT上传文件到AWS S3预设的url Retrofit2 Android

6 人关注

我有一个来自AWS S3的预签名的上传URL,用来上传一个视频文件。在Postman上测试,视频被成功上传。但在 retrofit 中执行时,我得到了 403 的返回。我不能为这个任务使用多部分上传。

服务电话 :

@Headers("Content-Type: video/mp4")
    fun uploadTaskAWS(@Url awsUrl: String, @Body filePart: RequestBody): Call<ResponseBody>
            val file = File(task.file_path)
            val requestFile = RequestBody.create(MediaType.parse("video/mp4"), file)
            val response = awsTaskUploadService.uploadTaskAWS(task.upload_url, requestFile)

我已经确保了URL是正确的。内容类型的标题也被添加了,附上postman的截图。得到403禁止的错误

邮递员的屏幕截图

我已经找到了这个相关的问题,但是我仍然得到一个403。使用Retrofit2将文件上传到AWS S3预签名的URL上

有什么建议吗?

android
amazon-s3
kotlin
retrofit
retrofit2
nt95
nt95
发布于 2019-03-14
3 个回答
nt95
nt95
发布于 2022-10-20
已采纳
0 人赞同

解决办法是包括多部分,并期待单一响应,而不是呼叫。

  @Multipart
    fun uploadAsset(
        @Header(CONTENT_TYPE) contentType: String,
        @Url uploadUrl: String,
        @Part file: MultipartBody.Part
    ): Single<ResponseBody>

其中contentType是以

val requestFile = RequestBody.create(MediaType.parse(contentType), file)
val body = MultipartBody.Part.createFormData(mediaType, task.file_name, requestFile)
assetService.uploadAsset(contentType, task.upload_url, body)
    
对于其他人来说,我也有同样的问题,建议的方法现在已经过时了,而且安卓现在使用内容提供者,使得访问底层文件变得棘手,如果感兴趣,我记录了我的解决方案 here
完美的解决方案。遵循@ZzAntáres提到的链接
谢谢你@ZzAntáres。
谢谢你,@ZzAntáres。你拯救了我。
单一是未定义的。从它应该添加的地方
Nikhil Sahu
Nikhil Sahu
发布于 2022-10-20
0 人赞同

403错误意味着服务器知道你是谁,但没有权力执行所需的行动。

如果预签名的URL是正确生成的,你应该能够在没有任何认证的情况下进行上传。

你可以检查postman是否默认在请求中添加任何AWS认证。

另外,如果上传到只使用版本4的地区,你需要在签署请求时明确设置协议版本。

你说的协议版本是什么意思?
Rajesh Satvara
Rajesh Satvara
发布于 2022-10-20
0 人赞同

我尝试了很多次改装,但都没有成功,最后我可以用HttpURLConnection来做。

 class UploadImageUsingPreSignedUrl(
    var bitmap: Bitmap?,
    var signedURL: String,
    var imageUploadCallback: ImageUploadCallback
) : AsyncTask<Void?, Void?, Int>() {
    override fun doInBackground(vararg p0: Void?): Int {
        var respCode = -1
        try {
            val url = URL(signedURL)
            val connection = url.openConnection() as HttpURLConnection
            connection.requestMethod = "PUT"
            connection.doOutput = true
            connection.setRequestProperty("Content-Type", "image/png") // your content type
            val outputStream = connection.outputStream
            bitmap?.compress(Bitmap.CompressFormat.PNG, 70, outputStream)
            outputStream.close()
            respCode = connection.responseCode
        } catch (e: Exception) {
            e.printStackTrace()
        return respCode
    override fun onPostExecute(responseCode: Int) {