使用预先签名的URL上传到AWS S3时出现随机-1响应状态

时间:2018-08-07 18:24:18

标签: angularjs amazon-web-services amazon-s3 upload pre-signed-url

我们的前端使用预签名的url将文档上传到S3,并且似乎随机失败。这部分功能对我们来说非常关键。

我们的预签名网址是由后端使用boto3生成的。

[...]
@classmethod
def get_presigned_url(cls, filename, user, content_type, size=None):
    client = cls.get_s3_client()
    import logging
    logging.info(cls.generate_keyname(filename, user))
    key = cls.generate_keyname(filename, user)
    params ={'Bucket': cls.s3_staging_bucket, 'Key': key,
             "ContentType": content_type}
    if size:
        params['ContentLength'] = size

    # It's private as default
    if cls.is_private:
        params['ACL'] = 'private'
    else:
        params['ACL'] = 'public-read'

    return client.generate_presigned_url(
        'put_object',
        Params=params,
        ExpiresIn=600
    ), cls.get_url(key, cls.s3_staging_bucket)
[...]

因此前端发送以下信息以请求上传链接:

        [...]
        // Request Presigned url
        Restangular.all('upload').all('get_presigned_url').post(
            {
                'resource_type': 'candidate-cv',
                'filename': vm.file.name,
                'size': vm.file.size || null,
                'content_type': vm.file.type || 'application/octet-stream'
            }
        ).then(
        [...]

上面的示例中需要注意的事项:sizetype并非在所有浏览器中都可用,因此我必须使用默认值。

一旦检索到链接,前端尝试直接将其上传到s3存储桶:

                [...]
                $http.put(
                    data['presigned_url'],
                    vm.file,
                    {
                        headers: {
                            'Content-Type':  vm.file.type || 'application/octet-stream',
                            'Authorization': undefined // Needed to remove default ApiKey
                        }
                    }
                ).then(
                [...]

上面的代码有时会给出-1响应。有时是一个问题,因为它经常发生。大概是3%的情况。

我们已经检查了插入的调试记录器,该记录器会针对每个错误的响应发送调试信息,但是似乎一切都很好。

到目前为止我们的事实:

  • 在开始时我似乎是连接问题,但是响应状态应该为0而不是-1?
  • 发生连接问题的频率很高(约3%)
  • 它发生在整个范围或新旧Windows / Mac Chrome / Edge Mobile / Desk用户代理上。
  • 它发生在整个文档格式docx / doc / pdf中。
  • 同一用户在1小时内连续尝试了几次,但均失败,结果为-1。
  • 具有相同用户代理的相同用户似乎能够在前一天或后一天成功上传。
  • 我们无法复制它。

我们做错了什么?我们应该朝哪个方向调查这个问题?我们应该采取哪些下一步措施解决问题?

感谢您的输入。

编辑:

@tcrite建议-1表示客户端超时。在本地环境中复制该问题似乎是正确的。我们更新了生产服务器,增加了较长的客户端超时时间:250秒。

但就在最近,我们收到了几个-1响应。用户尝试在2分钟内提交6次文件,所有结果均带有-1响应代码,并且存在超时配置:

响应:

{  
   "data":null,
   "status":-1,
   "config":{  
      "method":"PUT",
      "transformRequest":[  
         null
      ],
      "transformResponse":[  
         null
      ],
      "jsonpCallbackParam":"callback",
      "headers":{  
         "Content-Type":"application/msword",
         "Accept":"application/json, text/plain, */*"
      },
      "timeout":250000,
      "url":"https://stackoverflow-question.s3.amazonaws.com/uploads/files/a-b-a36b9b2f216..."
   }
}

这不是S3超时,因为我在本地环境中尝试以慢速连接的速度上传文件约5分钟,并且文件上传成功。

1 个答案:

答案 0 :(得分:0)

我认为您应该使服务器端Web应用程序上载文件(而不是基于angular的浏览器)。因为浏览器有时会受到公司政策的限制。 检查此python django应用程序。我相信您已经在使用python。

[https://testdriven.io/blog/storing-django-static-and-media-files-on-amazon-s3/][1]