直接从 url 上传文件到 S3 Bucket

Upload files to S3 Bucket directly from a url

我们需要将视频文件存储移动到 AWS S3。旧位置是一个 cdn,所以我每个文件只有 url(1000 多个文件,> 1TB 总文件大小)。 运行 不能直接在存储服务器上使用上传工具。

我已经创建了一个工具来下载文件、将文件上传到 S3 存储桶并使用新的 HTTP url 更新数据库记录,并且工作完美,只是需要很长时间。

下载文件需要一些时间(考虑到每个文件接近 1 GB),上传文件需要更长的时间。

是否可以直接从cdn上传视频文件到S3,这样我可以将处理时间减半?类似于读取文件块然后在读取下一个块时将其放入 S3。

目前我使用System.Net.WebClient下载文件,使用AWSSDK上传。

PS: 我对网速没有问题,我运行 应用程序在具有 1GBit 网络连接的服务器上。

不,没有办法指示 S3 代表您从非 S3 URL 获取资源并将其保存在存储桶中。

S3 唯一支持的类似“获取”的操作是 PUT/COPY 操作,其中 S3 支持从一个桶中获取对象并将其存储在另一个桶(或同一个桶)中,甚至跨区域,即使是跨账户,只要你有一个用户对交易两端的必要操作有足够的权限。在那种情况下,S3 在内部处理所有数据传输。

否则,获取远程对象并将其存储在 S3 中的唯一方法是下载资源,然后将其上传到 S3——但是,没有什么可以阻止您同时执行这两项操作。

为此,您需要编写一些代码,可能使用异步 I/O 或线程,以便您可以同时接收下载数据流并上传,可能以对称块的形式,使用 S3 的 Multipart Upload 功能,它允许您编写单独的块(每个块至少 5MB),对于最终请求,S3 将验证并合并到最大 5TB 的单个对象中。分段上传支持块的并行上传,并允许您的代码在不重新启动整个作业的情况下重试任何失败的块,因为 S3 不必按线性顺序上传或接收各个块。

如果源支持 HTTP range requests,您甚至不一定需要接收“流”,您可以发现对象的大小,然后 GET 按范围和多部分分块-上传它们。使用线程或异步 I/O 并行处理多个范围执行此操作,与在单个整体下载中下载它相比,您可能能够 更快 复制整个对象,取决于限制您下载速度的因素。

我使用这种技术从 AWS 外部将数 GB 的文件上传到 S3 时,总速度达到了 45 到 75 Mbits/sec。

我已经在 this question 中回答了这个问题,这里是要点:

object = Aws::S3::Object.new(bucket_name: 'target-bucket', key: 'target-key')
object.upload_stream do |write_stream|
  IO.copy_stream(URI.open('http://example.com/file.ext'), write_stream)
end

如果代理 (node express) 适合您,那么可以将这 2 条路由中的代码部分组合起来执行 GET POST 获取链,检索然后将响应正文重新发布到您的目的地。 S3 存储桶。

step one 创建 response.body

step two

将第二个 link 中的流设置为 link 1 中 GET op 的响应,您将上传到 dest.bucket 来自第一个 fetch[=12] 的流 ( arrayBuffer ) =]