GVKun编程网logo

如何在Go中将预签名的POST上传到AWS S3?

19

在本文中,我们将带你了解如何在Go中将预签名的POST上传到AWSS3?在这篇文章中,同时我们还将给您一些技巧,以帮助您实现更有效的ios–使用预签名URL将文件上传到AWSS3的代码有什么问题?、i

在本文中,我们将带你了解如何在Go中将预签名的POST上传到AWS S3?在这篇文章中,同时我们还将给您一些技巧,以帮助您实现更有效的ios – 使用预签名URL将文件上传到AWS S3的代码有什么问题?、iOS – 同步上传到AWS S3、java-使用Retrofit2将文件上传到AWS S3预签名URL、javascript – 如何使用Meteor将文件上传到Amazon S3?

本文目录一览:

如何在Go中将预签名的POST上传到AWS S3?

如何在Go中将预签名的POST上传到AWS S3?

我想执行一个预签名的POST以将文件上传到AWSS3存储桶-如何在Go中完成?

请注意,这与通过PUT进行预签名上传不同。

答案1

小编典典

因此,为了帮助他人,我将自己回答问题,并提供一些代码来帮助可能遇到相同问题的其他人。

可在此处找到Google App Engine呈现预签名POST表单的示例网络应用。

和一个小型图书馆,我创建做在Go预签POST。

简而言之,对公共读取的Amazon S3存储桶执行预签名的POST,您需要:

1.将S3存储桶配置为仅允许公共下载。

仅允许公共读取的示例存储桶策略。

{    "Version": "2012-10-17",    "Id": "akjsdhakshfjlashdf",    "Statement": [        {            "Sid": "kjahsdkajhsdkjasda",            "Effect": "Allow",            "Principal": {                "AWS": "*"            },            "Action": "s3:GetObject",            "Resource": "arn:aws:s3:::BUCKETNAMEHERE/*"        }    ]}

2.为允许上传的HTTP POST创建一个策略。

AWSS3文档

示例POST策略模板,带有过期时间,可以将特定密钥上载到特定存储桶中,并允许公众读取访问。

{ "expiration": "%s",    "conditions": [        {"bucket": "%s"},        ["starts-with", "$key", "%s"],        {"acl": "public-read"},        {"x-amz-credential": "%s"},        {"x-amz-algorithm": "AWS4-HMAC-SHA256"},        {"x-amz-date": "%s" }    ]}

3.使用S3存储桶所有者的凭据生成并签名策略。

AWS文档

  • 填写正确的值以表示到期时间,存储段,密钥,凭据和日期。
  • base64对策略进行编码。
  • HMAC-SHA256获取签名的策略。
  • 十六进制编码签名。

4.构造并发布多部分表单数据

AWS S3文档

现在,您要么生成HTML表单,然后自动获取正确的多部分表单数据请求,如上面的链接中所述。

我想在Go中手动完成此操作,所以这里是操作方法。

无论哪种方式,您都需要提供在步骤2和3中创建的POST策略中指定的所有部分。请求中除了强制性字段(策略中不包含)外,也不能有其他字段。

还指定了字段的顺序,并且它们都是HTTP POST请求中的多部分字段。

func Upload(url string, fields Fields) error {    var b bytes.Buffer    w := multipart.NewWriter(&b)    for _, f := range fields {            fw, err := w.CreateFormField(f.Key)            if err != nil {                    return err            }            if _, err := fw.Write([]byte(f.Value)); err != nil {                    return err            }    }    w.Close()    req, err := http.NewRequest("POST", url, &b)    if err != nil {            return err    }    req.Header.Set("Content-Type", w.FormDataContentType())    client := &http.Client{}    res, err := client.Do(req)    if err != nil {            return err    }    if res.StatusCode != http.StatusOK {            err = fmt.Errorf("bad status: %s", res.Status)    }    return nil}

ios – 使用预签名URL将文件上传到AWS S3的代码有什么问题?

ios – 使用预签名URL将文件上传到AWS S3的代码有什么问题?

我想使用预先签名的URL将文件从iOS App上传到AWS S3存储桶. URL是正确的,因为它在命令行上使用curl.
curl -v -k --upload-file FILENAME "https://MYBUCKET.amazonaws.com:443/KEYNAME?Signature=...&Expires=1391691489&AWSAccessKeyId=..."

使用以下Objective-C代码……

- (void)upload:(Nsstring *)url fileData:(NSData *)fileData
{
    NSMutableuRLRequest *request = [[NSMutableuRLRequest alloc] init];
    [request setURL:[NSURL URLWithString:url]];
    [request setHTTPMethod:@"PUT"];
    [request setHTTPBody:fileData];
    [request setValue:[Nsstring stringWithFormat:@"%d",[fileData length]] forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"audio/mpeg" forHTTPHeaderField:@"Content-Type"];
    [request setValue:@"public-read" forHTTPHeaderField:@"x-amz-acl"];
    [request setValue:@"iPhone-OS/6.0 fr_FR NE" forHTTPHeaderField:@"User-Agent"];

    _connection = [NSURLConnection connectionWithRequest:request delegate:self];
    [_connection start];
}

…我收到此错误:

Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x9c49560 {NSErrorFailingURLStringKey=https://MYBUCKET.s3.amazonaws.com:443/KEYNAME?Signature=...&Expires=1391703958&AWSAccessKeyId=...,NSErrorFailingURLKey=https://MYBUCKET.amazonaws.com:443/KEYNAME?Signature=...&Expires=1391703958&AWSAccessKeyId=...,NSLocalizedDescription=The request timed out.,NSUnderlyingError=0x9c48c80 "The request timed out."}

我使用WireShark查看是否有任何流量,并且流量很大.

我不知道我的代码有什么问题.似乎文件传输没有正确终止.

解决方法

我自己解决了这个问题Content-Type标头是罪魁祸首.在绝望中,我用一个非常小的文本文件测试了我的代码,并从S3获得了403作为HTTP状态代码.没有超时.这样的进步.我还收到了一条非常丰富的错误消息:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><StringToSignBytes>...</StringToSignBytes><RequestId>...</RequestId><HostId>...</HostId><SignatureProvided>...</SignatureProvided>
    <StringToSign>PUT

    text/plain
    1391784394
    KEYNAME</StringToSign>
    <AWSAccessKeyId>...</AWSAccessKeyId>
</Error>

显然,如果从客户端提供内容类型字符串(在本例中为text / plain),则在字符串到符号中是预期的.不要问我为什么这会导致大(5.5MB?)文件超时.我希望这能为其他人节省几个小时的生命.

最简单的解决方法是删除该行

[request setValue:@"..." forHTTPHeaderField:@"Content-Type"];

如果您在创建预签名URL时知道内容类型,则可以将字符串添加到字符串到符号.

iOS – 同步上传到AWS S3

iOS – 同步上传到AWS S3

所有aws-sdk-ios示例都使用awss3transfermanager异步上传数据.

例如:https://github.com/awslabs/aws-sdk-ios-samples/blob/master/S3TransferManager-Sample/Swift/S3TransferManagerSampleSwift/UploadViewController.swift#L81

现在通常,这很好,但由于其他原因,我的工作已经在NSOperation子类中了,所以我想同步上传到S3以保持简单(否则,我需要实现异步NSOperation,并且更多样板……)

有人知道怎么做吗?

解决方法

如果有人好奇,我想出来:

let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1,identityPoolId: AwsCognitoIdentityPoolId)
    let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1,credentialsProvider: credentialsProvider)
    AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration

    let S3Client = AWSS3.defaultS3()
    let putObjectRequest = AWSS3PutObjectRequest()
    putObjectRequest.bucket = AwsBucketName
    putObjectRequest.key = key
    putObjectRequest.body = logFilePathURL

    do {
        let fileAttributes = try self.fileManager.attributesOfItemAtPath(logFilePathURL.path!)
        let fileSizeNumber = fileAttributes[NSFileSize] as! NSNumber
        putObjectRequest.contentLength = NSNumber(longLong: fileSizeNumber.longLongValue)
    } catch _ as NSError {
        // Todo handle error
    }

    S3Client.putObject(putObjectRequest).continueWithBlock { (task: AWSTask) -> AnyObject? in
        return nil
    }.waitUntilFinished()

…是啊.我无法在任何地方找到一个例子,所以我必须阅读源代码并解决问题.至于那个aws-sdk-ios库,谈论过度工程……需要一段时间才能通过所有这些间接层来弄明白.

无论如何,在我返回nil的最后一个区块中,你处理错误等等.

java-使用Retrofit2将文件上传到AWS S3预签名URL

java-使用Retrofit2将文件上传到AWS S3预签名URL

我正在尝试使用预先签名的URL将文件上传到Amazon的S3.我从生成URL的服务器获取URL.将其作为JSON对象的一部分发送给我.我将URL作为字符串获取,如下所示:

https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/ImageName?X-Amz-Security-Token=xxfooxx%2F%2F%2F%2F%2F%2F%2F%2F%2F%2Fxxbarxx%3D&X-Amz-Algorithm=xxAlgoxx&X-Amz-Date=20170831T090152Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Credential=xxcredxx&X-Amz-Signature=xxsignxx

不幸的是,当我将其传递给Retrofit2时,它修改了String并试图将其制成URL.我已经设置了encoding = true,它可以解决大多数问题,但不能完全解决.我知道字符串按原样工作.我已经在Postman&得到成功的回应.

1st我尝试只是将String(除了我作为baseUrl剪切的东西)整体放入Path

public interface UpdateImageInterface {
    @PUT("{url}")
    Call<Void> updateImage(@Path(value="url", encoded=true) String url, Body RequestBody image);
}

调用代码:

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/")
            .build();

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class);
    // imageUrl is "ImageName..."
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile);

除“?”外,此方法大部分有效(在“ ImageName”之后)转换为“?”.这会导致请求错误/ 400.

我的下一个尝试是使用Retrofit2创建查询,然后将整个String(带有多个查询)转储到查询中.

public interface UpdateImageInterface {
    @PUT("ImageName")
    Call<Void> updateProfilePhoto(@Query(value="X-Amz-Security-Token", encoded = true) String token, @Body RequestBody image);
}

调用代码:

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://com-example-mysite.s3-us-east-1.amazonaws.com/userFolder/")
            .build();

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class);
    // imageUrl is "xxfooxx..."
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile);

这得到“?”正确呈现,但所有的’&’更改为“&”

最后,我尝试在baseUrl()中传递整个String,但是由于结尾没有’/’,因此给出了IllegalArgumentException.

我知道我可以解析预先签名的URL来进行多个查询,在应进行查询的情况下将它们组装在Retrofit2中,但我想避免这种处理.

要重申这个问题:

有没有一种方法可以使用Retrofit2轻松地(无需进行大量的字符串分析)将带有预签名URL的文件上传到S3?

解决方法:

在同事的帮助下,这就是解决方案.

public interface UpdateImageInterface {
    @PUT
    Call<Void> updateImage(@Url String url, @Body RequestBody image);
}

调用代码:

    String CONTENT_IMAGE = "image/jpeg";

    File file = new File(localPhotoPath);    // create new file on device
    RequestBody requestFile = RequestBody.create(MediaType.parse(CONTENT_IMAGE), file);

    /* since the pre-signed URL from S3 contains a host, this dummy URL will
     * be replaced completely by the pre-signed URL.  (I'm using baseURl(String) here
     * but see baseUrl(okhttp3.HttpUrl) in Javadoc for how base URLs are handled
     */
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://www.dummy.com/")
        .build();

    UpdateImageInterface imageInterface = retrofit.create(UpdateImageInterface.class);
    // imageUrl is the String as received from AWS S3
    Call<Void> call = imageInterface.updateImage(imageUrl, requestFile);

Javadoc获取@Url(类Url)&
baseUrl()(Retrofit.Builder类)

MediaType是OkHttp库中的一个类,经常与Retrofit(均来自Square)一起使用.可以在Javadoc中找到有关传递给parse方法的常量的信息.

javascript – 如何使用Meteor将文件上传到Amazon S3?

javascript – 如何使用Meteor将文件上传到Amazon S3?

我正在尝试将文件上传到我的Amazon S3 Bucket. S3和亚马逊成立.
这是亚马逊的错误消息:

Conflicting query string parameters: acl,policy

策略和签名被编码,对于Node.js使用Crypto.js

var crypto=Npm.require("crypto");

我正在尝试使用Meteor HTTP.post方法构建POST请求.这也可能是错误的.

var BucketName="mybucket";
    var AWSAccessKeyId="MY_ACCES_KEY";
    var AWSSecretKey="MY_SECRET_KEY";

    //create policy
    var POLICY_JSON={
        "expiration": "2009-01-01T00:00:00Z","conditions": [ 
            {"bucket": BucketName},["starts-with","$key","uploads/"],{"acl": 'public-read'},"$Content-Type",""],["content-length-range",1048576],]   
    }
    var policyBase64=encodePolicy(POLICY_JSON);
    //create signature
    var SIGNATURE = encodeSignature(policyBase64,AWSSecretKey);
    console.log('signature: ',SIGNATURE);

这是我与Meteor一起使用的POST请求:

//Send data----------
    var options={
        "params":{
            "key":file.name,'AWSAccessKeyId':AWSAccessKeyId,'acl':'public-read','policy':policyBase64,'signature':SIGNATURE,'Content-Type':file.type,'file':file,"enctype":"multipart/form-data",}
    }

    HTTP.call('POST','https://'+BucketName+'.s3.amazonaws.com/',options,function(error,result){
        if(error){
            console.log("and HTTP ERROR:",error);
        }else{
            console.log("result:",result);
        }
    });

她正在编码政策和签名:

encodePolicy=function(jsonPolicy){
    // stringify the policy,store it in a NodeJS Buffer object
    var buffer=new Buffer(JSON.stringify(jsonPolicy));
    // convert it to base64
    var policy=buffer.toString("base64");
    // replace "/" and "+" so that it is URL-safe.
    return policy.replace(/\//g,"_").replace(/\+/g,"-");
}

encodeSignature=function(policy,secret){
    var hmac=crypto.createHmac("sha256",secret);
    hmac.update(policy);
    return hmac.digest("hex");
}

A不知道发生了什么. POST方法或加密可能已经有问题,因为我不太了解这些方法.如果有人可以指出我正确的方向,编码或发送POST请求到AmazonS3正确,它可以帮助很多.
(我不喜欢使用filepicker.io,因为我不想强制客户端在那里注册.)

提前致谢!!!

解决方法

直接上传到S3可以使用 slingshot包:
meteor add edgee:slingshot

在服务器端声明您的指令:

Slingshot.createDirective("myFileUploads",Slingshot.S3Storage,{
  bucket: "mybucket",allowedFileTypes: ["image/png","image/jpeg","image/gif"],acl: "public-read",authorize: function () {
    //You can add user restrictions here
    return true;
  },key: function (file) {
    return file.name;
  }
});

该指令将自动生成策略和签名.

他们只是上传它:

var uploader = new Slingshot.Upload("myFileUploads");

uploader.send(document.getElementById('input').files[0],function (error,url) {
  Meteor.users.update(Meteor.userId(),{$push: {"profile.files": url}});
});

关于如何在Go中将预签名的POST上传到AWS S3?的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于ios – 使用预签名URL将文件上传到AWS S3的代码有什么问题?、iOS – 同步上传到AWS S3、java-使用Retrofit2将文件上传到AWS S3预签名URL、javascript – 如何使用Meteor将文件上传到Amazon S3?的相关信息,请在本站寻找。

本文标签: