我正在使用Rails 4为后端服务创建API.
该服务需要将图像文件上传到亚马逊s3存储桶.
该服务需要将图像文件上传到亚马逊s3存储桶.
我想使用直接上传网址,以便客户端管理上传到s3,服务器不会保持忙碌状态.
目前我有以下原型导轨动作
def create filename = params[:filename] s3_direct_post = S3_BUCKET.presigned_post(key: "offers/#{SecureRandom.uuid}/#{filename}",acl: 'public-read') s3p = s3_direct_post.fields url = "#{s3_direct_post.url}/#{filename}?X-Amz-Algorithm=#{s3p['x-amz-algorithm']}&X-Amz-Credential=#{s3p['x-amz-credential']}&X-Amz-Date=#{s3p['x-amz-date']}&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=#{s3p['x-amz-signature']}" render json: {success: true,url: url},status: :ok end
这会产生这样一个网址:
https://my-bucket.s3.eu-central-1.amazonaws.com/test.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MYKEY/20150420/eu-central-1/s3/aws4_request&X-Amz-Date=20150420T162603Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=MYSIGNATURE
现在我尝试使用以下内容将test.png发布到此URL:
curl -v -T test.png“url”
我收到以下错误响应:
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>MYKEY</AWSAccessKeyId>...
我认为问题来自于指定的X-Amz-SignedHeaders标头错误.我不确定默认情况下从amazon rails sdk gem使用哪些头文件.
解决方法
这是一个解决方案:
在config / initializers / aws.rb中:
AWS_CREDS = Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'],ENV['AWS_SECRET_ACCESS_KEY']) Aws.config.update({ region: 'eu-central-1',credentials: AWS_CREDS }) S3 = Aws::S3::Resource.new('eu-central-1') S3_BUCKET_NAME = ENV['S3_BUCKET_NAME'] S3_BUCKET = S3.bucket(S3_BUCKET_NAME)
在你的模型/控制器/关注/或其他:
obj = S3_BUCKET.object("offers/#{user.id}/#{self.id}") url = obj.presigned_url(:put) # obj.presigned_url(:put,acl: 'public-read') #if you want to make the file public
然后上传你可以使用移动客户端或卷曲:
curl -X PUT -T file_to_upload "url from above"
请注意,如果使用public-read acl选项,则必须添加x-amz-acl:public-read标头:
curl -H "x-amz-acl: public-read" -X PUT -T file_to_upload "url from above"