2016-11-27 128 views
0

我试图上传文件到S3,而不必发送到我的服务器。我有一个端点,它给了我签名的S3 URL,在那里我可以发出PUT请求将文件存储到我的存储桶中。上传图像到S3不起作用

我试图做一些JavaScript方面没有工作的东西。 (我没有使用Amazon的SDK,并且不希望,因为我在寻找简单的文件上传,没有什么比这更)

这里就是我想目前在JavaScript中执行:

uploadToS3 =() => { 
    let file = this.state.files[0]; 
    let formData = new FormData(); 
    formData.append('Content-Type', file.type); 
    formData.append('file', file); 
    let xhr = new XMLHttpRequest(); 
    xhr.open('put', this.signed_url, true); 
    xhr.send(formData) 
}; 

我尝试了一堆选项,我更喜欢使用fetch,因为我并不真正关心上传进度,因为这些只是图像。我从某处使用xhr代码尝试如上。这些做网络电话,似乎他们应该工作,但他们不。

发生了什么:在S3上创建一个对象,当我进入公共URL时,它们被下载,当我使用图像查看器打开它们时,它们会说它不是有效的JPG。

我在想我没有正确地上传。

这是我在邮递员怎么办:

Postman with file chosen

通知我有正确标识的URL,我已经把它贴二进制映像文件的请求。并增加了一个标题,说明内容类型为图像/ JPEG,如下图所示:

Specified headers

当我登录到S3和去我斗,我可以看到一个形象,我可以去它的公共URL和视图在浏览器中。这是完美的,正是我想要的,现在我不知道如何在JavaScript上实现同样的效果。

PS:我甚至试图点击邮递员上的code,它不会为我生成文件代码。

+0

'xhr.send(formData)'...没有意义。当你在S3中放入一个文件时,你根本不使用任何形式的结构*,你只需发送正文。 'Content-Type:'进入请求标题,而不是在主体中的formdata中。 (对于其他标题也是如此)。下载您上传的文件并使用文本编辑器查看。一旦你看到你的代码实际发送给S3,这个问题应该非常明显,S3然后顺从地存储和提供后续请求。 –

+0

哇// @ Michael-sqlbot,我感觉不到更愚蠢:D我以为我试过这个。但显然它现在起作用。你可以发表你的评论作为答案,所以我可以接受它吗?谢谢!你救了我! –

+0

谢谢。按要求完成。 –

回答

1

这里的问题始于xhr.send(formData)

当您在0123中使用PUT文件时,您根本不使用任何表单结构,只需在请求正文中发送原始对象字节。

Content-Type:和其他元数据进入请求标题,而不是正文中的表单数据。

在这种情况下,如果您下载上传的文件并使用文本编辑器进行查看,那么一旦您看到代码实际发送到S3时,问题应该非常明显,S3随后会顺从地存储并随后提供要求。

请注意,S3确实支持browser-based form POST uploads,但是这样做时签名过程会有很大差异,要求您创建并签署策略文档,以便您可以将表单(包括策略和签名)发送到浏览器并允许否则不信任的用户上传文件 - 已签名的策略语句可防止浏览器用户篡改表单并执行您不打算执行的操作。

+0

嗨,我还有一个小问题,不知道我是否应该问这里, $ config = [ 'Bucket'=> env('BUCKET'), 'ACL'=>'public-read' , 'Key'=> $ key, 'CacheControl'=>'max-age = 172800', 'Expires'=> new \ DateTime('+ 2 days'), ];如果($ contentType){ $ config ['contentType'] = $ contentType; $ this-> s3-> createPresignedRequest($ this-> s3-> getCommand('PutObject',$ config),$ expiry); $ this-> s2-> 未考虑到期限。而且我的图像不可破解。任何想法? –

+0

对不起,不知道如何在评论中发布代码。 –

+0

@NishchalGautam我会建议发布这个作为一个新的问题。我和其他许多专家在我们专业领域的所有新问题中都会定期收到通知。高质量的问题通常不会得到答复。上传文件,然后从S3下载它,捕获响应头文件,并将其包含在您的问题中。 '$ expiry'(如果正确传递)指定在生成URL之后,您可以使用预先签名的URL上载多长时间,然后URL本身不再允许您将其用于上传 - 它与缓存下载无关。 –