我们在Amazon S3上存储了大量文件,我们希望网站访问者能够通过AJAX访问,但我们不希望向访问者透露实际的文件位置。
为了实现这一点,我希望做的是向一个非常简单的perl脚本发出一个AJAX请求,该脚本只是作为代理并将文件返回给浏览器。我已经有脚本设置来验证用户是否已登录并进行数据库查询以找出正确的URL以访问S3上的文件但我不确定将文件返回到vistor浏览器的最佳方法最有效的方式。
对于实现这一目标的最佳方法的任何建议将不胜感激。谢谢!
答案 0 :(得分:2)
最好的方法是使用sendfile
system call。如果您手动打开并从磁盘读取文件,然后再次将其按块写入Web框架的“接收器”端,那么您将非常浪费,因为数据必须通过RAM传输,可能包括缓冲。 / p>
您在问题中描述的是一种非常常见的模式,因此围绕设置special HTTP header的想法已经存在许多解决方案,然后让应用程序下面的Web堆栈有效处理它。
在Plack中使用XSendfile中间件来设置适当的标头。以下最小程序将DTRT并尽可能利用系统调用。
use IO::File::WithPath qw();
use Plack::Builder qw(builder enable);
builder {
enable 'Plack::Middleware::XSendfile';
sub {
return [200, [], IO::File::WithPath->new('/usr/src/linux/COPYING')];
}
};
答案 1 :(得分:1)
确定。有一个例子是如何使用Mojolicious框架实现它。
我想你将这个脚本作为守护进程运行。脚本捕获对/json_dir /。*的所有请求,此请求到Stackoverflow API并返回响应。
您可以将此脚本作为./example.pl daemon
运行,然后尝试http://127.0.0.1:3000/json_dir/perl
作为回应,您应该能够找到自己的题为“Simple Perl Proxy”的问题。 此代码可用作侦听某些端口和CGI脚本的独立守护程序(首选)。
#!/usr/bin/env perl
use Mojolicious::Lite;
get '/json_dir/(.filename)' => sub {
my $self = shift;
my $filename = $self->stash('filename');
my $url = "http://api.stackoverflow.com/1.1/questions?tagged=" . $filename;
$self->ua->get(
$url => sub {
my ($client, $tx) = @_;
json_response($self, $tx);
}
);
$self->render_later;
};
sub json_response {
my ($self, $tx) = @_;
if (my $res = $tx->success) {
$self->tx->res($res);
}
else {
$self->render_not_found;
}
$self->rendered;
}
app->start;
__DATA__
@@ not_found.html.ep
<!doctype html><html>
<head><title>Not Found</title></head>
<body>File not found</body>
</html>