我的Elixir / Phoenix应用程序需要能够录制HTML5视频,允许用户查看他们录制的视频,然后通过AJAX将录制内容直接上传到S3进行存储,并向Elixir服务器发送POST以存储新上传的视频宾语。在Rails世界中,有关于如何实现这一目标的各种宝石和冗长的教程;什么是Elixir / Phoenix直接上传S3文件的简单方法?
答案 0 :(得分:6)
我最终解决了这个问题。需要在S3帐户上进行设置,添加服务器端代码以及添加客户端代码。
首先,您需要一个AWS账户和一个S3存储桶。创建存储桶。
在存储桶设置中 - >权限 - >公共访问设置,确保"阻止新的公共ACL和上传公共对象"和"删除通过公共ACL授予的公共访问权限#34;是不检查。
然后在Permissions下 - >在CORS配置中,添加CORS配置以允许来自您站点的跨域浏览器请求,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://localhost:4000</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
(为您的网站可访问的每个来源指定一个<AllowedOrigin>
语句,或者如果您不担心CORS安全性,请将AllowedOrigin设置为*
。)
良好的卫生条件还包括设置只能访问此S3存储桶的IAM角色,以及仅允许您允许的特定操作。然后,在服务器设置步骤中,您将提供IAM角色的访问凭据,而不是您的AWS账户访问凭据。我在此处显示的代码中跳过了此步骤。
确保安装了ex_aws
软件包和所有依赖项(注意版本,以避免使用无效的预分配网址的错误):
# in mix.exs, in the deps list
# Stay at 2.0 to avoid presigned url bug: https://github.com/ex-aws/ex_aws/issues/602
{:ex_aws, "2.0.1"},
# :arc S3 integration
{:ex_aws_s3, "~> 2.0"},
# required by :ex_aws
{:sweet_xml, "~> 0.6"},
在config/config.exs
中,提供您的AWS访问凭据和S3设置:
config :ex_aws,
access_key_id: System.get_env("AWS_ACCESS_KEY_ID"),
secret_access_key: System.get_env("AWS_SECRET_ACCESS_KEY"),
region: "us-east-1",
s3: [
scheme: "https://",
host: "s3.amazonaws.com",
region: "us-east-1" ]
(要与Heroku兼容,我将敏感值存储在config/secrets.exs
中设置的环境变量中,这些变量从Git仓库中排除。)
现在设置控制器操作,该操作呈现将在其上进行S3文件上载的页面。最小控制器操作可能如下所示:
def edit(conn, %{"id" => id}) do
render conn, "edit.html", presigned_s3_url: presigned_s3_url(id)
end
defp presigned_s3_url(id) do
bucket = System.get_env("S3_BUCKET")
path = "uploads/interview_recordings/#{id}.webm"
{:ok, url} = ExAws.S3.presigned_url(ExAws.Config.new(:s3), :put, bucket, path,
query_params: [
# Set permissions so public can view this file
{"x-amz-acl", "public-read"},
{"contentType", "binary/octet-stream"}
]
)
url
end
此#edit操作提供了一个变量@presigned_s3_url
,它授权我们的客户端代码将文件上传到S3。请注意调用:put
时指定的ExAws.S3.presigned_url
方法;如果您指定不同的请求方法或省略查询参数等,S3上传请求可能会被拒绝。您在此处指定的参数必须与实际AJAX请求的参数完全匹配,否则S3将拒绝上传,因为签名S3生成的符号与我们生成的签名不匹配。
您的设置会有所不同,因此我不会粘贴任何HTML标记。唯一重要的部分是:一些客户端操作(在我的情况下,记录HTML5视频)导致文件可供浏览器JS使用,并且当客户端点击&#34;提交&#34;按钮,我们向附带文件数据的已签名S3 url发出PUT请求。我的AJAX调用如下所示:
$('.js-submit-recording').click(function(e) {
e.preventDefault();
console.log("Uploading the recording to S3...");
$.ajax({
url: $(this).data('presigned-s3-url'), // the url we generated server-side
type: "PUT",
contentType: "binary/octet-stream",
processData: false, // Treat the data as a raw file, not as a POST form
data: recording_data, // a blob object
success: function() {
console.log("File successfully uploaded!");
// Now you can initiate next steps like making a POST request to our
// Phoenix server to record the newly uploaded file in our db
},
error: function() {
console.log("File not uploaded :-/");
console.log(arguments);
// If you get errors, open Chrome's Network tab and look at the
// response body for the S3 request. It will describe the reason /
// error and some details that can help with troubleshooting.
}
});
});
这应该让基础工作正常运作!
答案 1 :(得分:0)
基本上你需要阅读this教程。
您使用的只是Arc
,并使用ex_aws
。您必须在配置文件中添加s3的配置,并基本上使用Arc调整您的JS。
如果您不想在数据库中存储这些文件,请直接在代码中使用name_of_your_uploader.store
。如果你想用AJAX这样做,你可以用频道来做。