我正在尝试组合一个接收文件路径的函数,识别它是什么,设置适当的头,并像Apache一样提供服务.
我这样做的原因是因为我需要在提供文件之前使用PHP来处理有关请求的一些信息.
速度至关重要
virtual()不是一个选项
必须在共享托管环境中工作,用户无法控制Web服务器(Apache/nginx等)
这是我到目前为止所得到的:
File::output($path);
<?php
class File {
static function output($path) {
// Check if the file exists
if(!File::exists($path)) {
header('HTTP/1.0 404 Not Found');
exit();
}
// Set the content-type header
header('Content-Type: '.File::mimeType($path));
// Handle caching
$fileModificationTime = gmdate('D, d M Y H:i:s', File::modificationTime($path)).' GMT';
$headers = getallheaders();
if(isset($headers['If-Modified-Since']) && $headers['If-Modified-Since'] == $fileModificationTime) {
header('HTTP/1.1 304 Not Modified');
exit();
}
header('Last-Modified: '.$fileModificationTime);
// Read the file
readfile($path);
exit();
}
static function mimeType($path) {
preg_match("|\.([a-z0-9]{2,4})$|i", $path, $fileSuffix);
switch(strtolower($fileSuffix[1])) …Run Code Online (Sandbox Code Playgroud) 我一直在研究使用Django进行访问控制的文件下载.我的目标是完全阻止对文件的访问,除非由特定用户访问.我已经读过,当使用Django时,X-Sendfile是实现这一目标的首选方法之一(基于其他SO问题等).我对使用Xang Sendfile和Django的基本理解是:
与直接从Django中删除文件相比,X-Sendfile似乎是一种更有效的方法来实现受保护的下载(因为我可以依赖Nginx来提供文件,而不是Django),但是给我留下两个问题:
public_html目录中)?或者,精通技术的用户是否可以检查标题等,并以反向工程方式访问文件(然后分发)?提前致谢.
我使用以下代码在Rails中发送文件.
if File.exist?(file_path) send_file(file_path, type: 'text/excel') File.delete(file_path) end
在这里,我试图发送文件,并在成功发送后从服务器中删除该文件.但我面临的问题是,删除操作是在发送执行时执行的,因为我在浏览器中看不到任何内容.
所以在Rails中有任何方法,一旦send_file操作完成,从服务器删除文件.
任何有关这方面的帮助将受到高度赞赏.
谢谢,
Chetan
我似乎找不到很多关于X-Sendfile或PHP示例代码的文档(有一些rails代码).
以前有人用过它,会介意快速提供代码片段和简要说明吗?
我有一个应用程序服务大(几百MB)的视频文件,它在桌面浏览器上完美运行,在Apache上使用Rails + X-Sendfile.一个重要的要求是这些视频必须是私有的,并且只对已登录的用户可见,因此这就是我使用Rails为其提供服务的原因.
一切都与其他设备完美配合.我以这种方式提供视频:
response.headers["X-Sendfile"]= filename
send_file filename, :disposition => :inline, :stream => true, :x_sendfile => true
Run Code Online (Sandbox Code Playgroud)
但是Ipad的请求需要字节范围头.解决方案(不能完美运行)是这样的:
size = File.size(filename)
bytes = Rack::Utils.byte_ranges(request.headers, size)[0]
offset = bytes.begin
length = bytes.end - bytes.begin
response.header["Accept-Ranges"]= "bytes"
response.header["Content-Range"] = "bytes #{bytes.begin}-#{bytes.end}/#{size}"
send_data IO.binread(filename,length, offset), :type => "video/mp4", :stream => true, :disposition => 'inline', :file_name => filename
Run Code Online (Sandbox Code Playgroud)
有了这个解决方案,我遇到了大于50mb视频的问题,而且更重要的是,我给了rails一个不应该有的责任.通过x-sendfile模块处理流的繁重负载应该是apache.但我不知道如何.该send_data方法没有x-sendfile参数,涉及send_file方法的解决方案不起作用.
我发现这两个问题与我的相似,但它们不起作用:rails media file stream通过send_data或send_file方法接受字节范围请求,通过rails向Ipad提供mp4文件的正确方法是什么?
关于发生了什么的任何线索?我几周以来一直在努力,我需要让它发挥作用.欢迎其他可行的解决方案.
ruby-on-rails x-sendfile video-streaming ipad ruby-on-rails-4
假设我有一个由nginx提供的Rails 2.3.2应用程序,并由mongrel提供服务,其中我需要通过Rails提供大型静态文件(以控制对它的访问).我希望Rails应用程序将文件传输委托给nginx,以避免阻止mongrel实例.
可用的信息似乎是矛盾和不完整的.这篇文章展示了如何用Apache做到这一点,并暗示它也可以用ngninx完成 - 但没有例子.这篇文章和这篇文章展示了如何使用一个显然Rails 2.3使得不必要的插件来实现它.这篇文章表明可能毕竟不支持带有nginx的x-sendfile.
对于Rails现在可以自行完成的事情,我宁愿不要使用插件.
有没有人使用没有插件和Rails 2.3/nginx/mongrel的x-sendfile式行为?如果没有,那么使用插件(和/或monkeypatch)和Rails 2.3/nginx/mongrel的最佳文档是什么?
我有一个PHP文件,唯一的工作是检查用户是否登录+如果设置了会话变量,然后通过nginx X-Sendfile传递文件.它可以在任何桌面浏览器上完美运行,以前可以在任何移动浏览器上运行 - 但在任何只有mp4的ios 10浏览器上都会失败.对我来说没什么意义的是,如果我评论该die()行,它会按预期工作,但PHP代码应该永远不会进入该行.
<?php
require_once('authConfig.php');
$userInfo = $auth0->getUser();
session_start();
include('cururl.php');
$murl = curPageURL();
parse_str($murl, $result);
$filename=$result['file'];
$folder=$result['folder'];
if (!$userInfo || !isset($_SESSION[$folder])) {
header('Location:login.php');
die();
}
$file="/var/www/uploads/" . $folder . "/" . $filename;
$aliasedFile = '/protected/' . $folder .'/' . $filename;
$realFile = $file;
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: ' . mime_content_type($file));
header('Content-Length: ' .(string)(filesize($realFile)) );
header('X-Accel-Redirect: ' . $aliasedFile);
exit;
?>
Run Code Online (Sandbox Code Playgroud)
我可以$_SESSION[$folder]通过将代码更改为:
if(isset($_SESSION[$folder])){
echo "OK";
die();
}
Run Code Online (Sandbox Code Playgroud)
更新:这是来自iPhone的访问日志.它应该有权访问该文件.
10.0.0.1 forwarded for ..., 10.0.0.1 …Run Code Online (Sandbox Code Playgroud) 我在Ubuntu 8.04上使用Nginx 1.0.0和Passenger 3.0.7运行Rails 3站点.
在我的Nginx error.log中,我开始看到X-Accel-Mapping header missing相当多的消息.谷歌搜索导致我的文档Rack::Sendfile,并在Nginx的文档.
现在,我的应用程序可以通过多个域访问,我send_file在我的应用程序中使用它来提供特定于他们请求的域的一些文件,例如,如果你来domain1.com/favicon.ico我查找favicon in public/websites/domain1/favicon.ico.这工作正常,我认为我不需要/想要让Nginx参与并创建一些私有区域,我存储这些文件,正如Rack::Sendfile文档中的示例所示.
我怎样才能摆脱错误信息?
我有以下问题.声音在公共文件夹中隐藏,因为只有某些用户应该有权访问声音文件.所以我做了一个特定的方法,它就像一个声音网址,但首先计算,是否允许当前用户访问此文件.
该文件由send_data方法发送.问题是,如果它工作得很好我工作得很慢...我用来播放声音的jplayer插件的开发者告诉我,我应该能够接受字节范围请求以使其正常工作...
如何通过发送带有send_data或send_file的文件在rails控制器中执行此操作?
谢谢你,马库斯
我试图建立一个站点,以便用户只能访问自己的图像和音频文件。为此,我在URL中使用了变量,例如:
<img src="/public/get_file.php?type=image&file=pic001.png" />
Run Code Online (Sandbox Code Playgroud)
在前端,我正在使用React JS(不确定这对这个问题是否重要)。但是在后端,PHP脚本将验证用户已登录(仅通过检查一个简单的SESSION变量),并在用户的数据目录中查找该文件(基于其SESSION变量中的用户ID)。如果存在,它将使用XSendFile将其返回给用户。
我遇到的问题是,每次用户尝试访问文件时,在加载文件之前都会有一些延迟。这告诉我它们可能没有被浏览器缓存。
为什么文件没有被缓存?它与URL参数有关还是与PHP / XSendFile的使用有关?
如何允许我的文件(图像/音频)被缓存?
更新资料
根据要求,这里是我的get_file.php:
<?php
session_start();
if (empty($_SESSION['auth']['id'])){
exit;
}
require_once("../../api_modules/settings.php");
$developer_id = $_SESSION['auth']['id'];
$type = preg_replace('/[^-a-zA-Z0-9_]/', '', $_GET['type']);
$file = preg_replace('/[^-a-zA-Z0-9_\.]/', '', $_GET['file']);
$file = preg_replace('/[\.]{2,}/', '', $file);
$project_id = preg_replace('/[^0-9]/', '', $_GET['project_id']);
$developer_id = preg_replace('/[^0-9]/', '', $developer_id);
if ($type == "image")
$file = FILEPATH ."files/$developer_id/$project_id/images/thumbs/88x88/$file";
else if ($type == "full_image")
$file = FILEPATH ."files/$developer_id/$project_id/images/originals/$file";
else if ($type == "audio"){
$file = FILEPATH ."files/$developer_id/$project_id/audio/$file";
}
else {
exit;
}
header("X-Sendfile: …Run Code Online (Sandbox Code Playgroud)