获取请求文件大小的.htaccess规则

时间:2013-08-20 06:22:46

标签: regex apache .htaccess mod-rewrite

我想知道是否会有这样的事情。我想检查文件的大小,然后根据它做htaccess规则。例如:

# like this line
CheckIf {REQUESTED_FILE_SIZE} 50 # MB
AuthName "Login title"
AuthType Basic
AuthUserFile /path/to/.htpasswd
require valid-user

很明显,我想制作一些特定文件大小的文件,仅供某些用户使用(使用身份验证)

任何想法都表示赞赏。

更新#1

应该在htaccess

中完成

更新#2

有很多文件,他们的网址已在博客中发布。因此,无法将较大的文件分隔到另一个文件夹并更新每个帖子,以后文件大小的限制也可能会发生变化。

更新#3

这是一个带PHP和Linux的Windows服务器安装了helicon App

更新#4

有些人对真正的问题感到困惑,我也不清楚它。

.htaccess + 用于身份验证的PHP文件(使用API​​)和检查文件大小 + 所有可下载文件都在同一服务器中我们的网站托管在不同的服务器上。

5 个答案:

答案 0 :(得分:3)

显然.htaccess无法检查所请求的文件大小并采取相应措施。您可以做的是使用External Rewriting Program feature of RewriteMap

您需要首先定义一个RewriteMap这样的Apache配置:

RewriteMap checkFileSize prg:/home/revo/checkFileSize.php

然后在.htaccess内部通过传递来定义这样的规则:

RewriteRule - ${checkFileSize:%{REQUEST_FILENAME}}

%{REQUEST_FILENAME}传递给STDIN上的PHP脚本。

然后在/home/revo/checkFileSize.php内,您可以放置​​PHP代码来检查文件的大小,并按照重定向到显示基本身份验证对话框的URI进行相应操作。

答案 1 :(得分:2)

我分两步完成:

1:htaccess将所有请求重定向到一个php脚本,假设你的文件在/test/内,并且你想让它全部由/test/index.php处理,例如:

RewriteEngine On
RewriteBase /test
RewriteCond %{REQUEST_URI} !/test/index.php
RewriteRule ^(.+)? /test/index.php?file=$1 [L]

RewriteCond只是为了避免循环请求。

2:index.php脚本根据请求的文件大小执行所有auth逻辑,如下所示:

define('LIMIT_FILESIZE',50*1024*1024); // eg.50Mb
define('AUTH_USER', 'myuser');         // change it to your likes
define('AUTH_PW','mypassword');        // change it to your likes

if( filesize($_GET['file'])>LIMIT_FILESIZE ){
  if( !isset($_SERVER['PHP_AUTH_USER']) ) {
    header('WWW-Authenticate: Basic realm="My realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Canceled';
    exit;
  } 
  else if( $_SERVER['PHP_AUTH_USER']!=AUTH_USER &&
           $_SERVER['PHP_AUTH_PW']!=AUTH_PW ) {
    header('HTTP/1.0 401 Unauthorized');
    echo 'Wrong credentials';
    exit;
  }
}

// If we're here, it's fine (filesize is below or user is authenticated)
// offer file for download
$file = rawurldecode($_GET['file']);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file( $finfo, $file );
header("Content-type: ".$mime );
header("Content-Disposition: attachment; filename=".basename($file));
include( $file );

它有许多可能的改进,但它应该作为基础。

答案 2 :(得分:2)

我认为来自@Paolo Stefan和@anubhava的答案都是有效的(+1)。

请注意,使用RewriteMap将强制修改apache配置,而不仅仅是.htaccess文件。实际上,如果您对性能有所了解,应将.htaccess文件中的所有内容放入<directory /same/filesystem/path/as/the/.htaccess/file/>指令中,并在VirtualHost配置中放置AllowOverride None。通过避免每个查询的apache的文件I / O和动态检查配置文件设置,你肯定会获得一些速度(.htaccess文件很糟糕,真的)。因此, RewriteMap 在.htaccess中不可用的事实应该不是问题。

这两个答案提供了一种基于文件大小来改变Authentification标头的方法。现在,您忘记提及的一个重要事实是,文件不能直接在PHP服务器上的同一台服务器上使用,而且您不希望每次下载时都启动脚本。

使用当前的@anubhava解决方案,您可以在操作系统上调用每次访问时的文件大小,当然这个脚本应该在文件存储服务器上运行。

一种解决方案可能是存储某个地方(专用数据库或密钥值存储?)文件大小索引。您可以在每次下载后提供此索引,您可以管理一些异步任务来维护它。然后在文件存储服务器的apache配置中,您必须启动脚本检查文件大小。使用RewriteMap您有几个选择:

  • 使用非常快scriptprg:关键字(用C语言编写,Perl,任何东西,你都不依赖于PHP),在这个数据存储中请求这个文件大小的索引,甚至fastdbd:直接在apache中执行SQL查询。但这意味着每个请求都有一个查询,因此您可以使用其他解决方案。
  • 带有txt:关键字的
  • use directly o mapping file,每个文件名已经计算出匹配的大小,不再有查询,只需
  • 更好的是,使用hashmap of this file和dbm:`keyword。

使用最后两个选项,文件大小索引是此文本文件的文本文件或散列版本。当文件的修改时间被更改时,Apache正在缓存hashmap并在重新启动时重新计算缓存。所以你只需要在每次下载后重新计算这个hashmap,以便在rewriteRule中获得非常快速的文件大小检查,如anubhava所示,但是使用

RewriteMap checkFileSize dbm:/path/to/filesize_precomputed_index.map

您还可以尝试在文件服务器上使用mod_security并检查Content-Length标头以添加HTTP身份验证。检查this thread是否有关于该主题的答案的开头。但mod_security配置并非易事。

答案 3 :(得分:1)

不是直接的,但只需对文件系统进行一些修改即可。

如果这是一个用户上传以及下载的系统,您可以关闭Content-Length中的mod_rewrite标题,将较大的文件放入单独的文件中目录。 (或者,如果您可以通过其他方式在上传时移动它们)

接下来,在包含较大文件的目录中,您将其设置为要求对所有文件进行身份验证。

最后使用mod_rewrite中的存在测试来透明地将用户重定向到large_files目录(如果文件在那里)。

如果您无法移动文件,可以使用符号链接来设置两个布局。

答案 4 :(得分:1)

根据this mod_rewrite支持"-s" CondPattern ,它会检查指定的 TestString 是否为非常规文件零大小。附加的patch扩展了"-s"选项,以支持对任意大小的比较。

所以质疑:

CheckIf {REQUESTED_FILE_SIZE} 50 # MB

应该使用此 .htaccess 代码:

RewriteCond %{REQUEST_FILENAME} -s=52428800