Amazon s3 键有前导斜杠时如何使用GetObject

Amazon s3 键有前导斜杠时如何使用GetObject,amazon-s3,aws-sdk-go,Amazon S3,Aws Sdk Go,我需要使用Go AWS SDK中的GetObject函数系列从S3 bucket中获取一个对象,其中对象的键可能以一个或多个斜杠开头。但是,SDK似乎删除了那些主要的斜杠,从而更改了密钥 我创建了bucket并将一些数据放入其中,如下所示: $ aws s3 mb <TEST BUCKET> $ aws s3 cp <SOME FILE> s3://<TEST BUCKET>//leadingslash 在启用调试日志记录的情况下调用GetObject,表明

我需要使用Go AWS SDK中的
GetObject
函数系列从S3 bucket中获取一个对象,其中对象的键可能以一个或多个斜杠开头。但是,SDK似乎删除了那些主要的斜杠,从而更改了密钥

我创建了bucket并将一些数据放入其中,如下所示:

$ aws s3 mb <TEST BUCKET>
$ aws s3 cp <SOME FILE> s3://<TEST BUCKET>//leadingslash
在启用调试日志记录的情况下调用
GetObject
,表明SDK执行以下请求:

GET /leadingslash HTTP/1.1
这缺少前导斜杠并返回404错误

如何使用go SDK获取此类对象 ?我无法控制对象的关键点

在将键传递到
GetObject
之前,我尝试过对其进行URL转义,但是转义了百分号,并且键发生了更改


我使用Go 1.9 linux/amd64和SDK 1.12.62。

根据@michael sqlbot的建议,通过使用自定义逻辑构建请求解决了这一问题:

主程序包
进口(
“fmt”
“io/ioutil”
“net/http”
“时间”
“github.com/aws/aws sdk go/aws/credentials”
“github.com/aws/aws sdk go/aws/signer/v4”
“github.com/aws/aws sdk go/private/protocol/rest”
)
常数(
BUCKET=“”
KEY=“/leadingslashkey”
REGION=“”
)
func main(){
凭据:=凭据。NewEnvCredentials()
签名者:=v4.NewSigner(凭据)
请求,错误:=http.NewRequest(
http.MethodGet,
fmt.Sprintf(“https://%s.s3.%s.amazonaws.com/%s”,BUCKET,REGION,rest.EscapePath(KEY,false)),
无
)
如果错误!=零{
println(err.Error())
返回
}
标头,错误:=签名者。签名(
要求
无
“s3”,
区域
时间。现在(),
)
如果错误!=零{
println(err,err.Error())
返回
}
fmt.Printf(“%#v\n”,标题)
fmt.Printf(“%#v\n”,请求)
客户端:=http.client{}
响应,错误:=client.Do(请求)
如果错误!=零{
println(err,err.Error())
返回
}
fmt.Printf(“%#v\n”,响应)
out,Util:=ioutil.ReadAll(response.Body)
println(字符串(输出))
}

也有同样的问题,但经过一段时间的努力和调试,我找到了另一个解决方案

解决方案是将其添加到s3客户机配置中

DisableRestProtocolURICleaning: aws.Bool(true),
发件人:

自动URI清理

与关键帧包含相邻斜线的对象交互(例如。 bucketname/foo//bar/objectname)需要设置 DisableRestProtocolURICleaning在使用的aws.Config结构中设置为true 由服务客户端执行


键中的前导斜杠基本上是不正确的,因为从概念上讲,URL中的
/
位于对象键中第一个字符之前,而不是键本身的第一个字符(很像服务器根目录中的文件实际上被命名为
foo
,而不是
/foo
,前者是名称,后者是路径)…但不幸的是,大多数SDK在开发人员错误地提供前导斜杠时吞下了前导斜杠,从而掩盖了这一点。如果无法更正错误的密钥,您可能必须破解SDK或使用自己的签名代码。
svc := s3.New(sess, &aws.Config{
    DisableRestProtocolURICleaning: aws.Bool(true),
})
out, err := svc.GetObject(&s3.GetObjectInput {
    Bucket: aws.String("bucketname"),
        Key: aws.String("//foo//bar//moo"),
})