.htaccess to get the requested file size

I wonder if there could be such a thing. I want to check the file size and then execute the htaccess rules based on it. For instance:

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

Clearly, I want some files with a specific file size to be available only to some users (using authentication)

Any idea is welcome.

Update # 1

should be done in htaccess

Update # 2

There are so many files, and their URLs are already posted on the blog. Therefore, you cannot separate larger files from another folder and update each record, as well as the file size limit may change in the future.

Update # 3

This is a Windows server with PHP and helicon installed.

Update # 4

Some people got confused about the real problem, and I also did not understand it.

.htaccess + PHP file for authentication (uses API) and file size verification + All downloaded files are on one server BUT our site is hosted on another server.

+6
source share
6 answers

At the time I asked if Apache 2.4 was there, so this answer might be correct.

Apache Expressions

Starting with Apache 2.4, a new feature called Expressions has appeared . Accordingly, you can use some functions in your directives, as well as in combination with RewriteCond .

Fortunately, there is a function called filesize() that can compare file sizes with comparison operators: -et -gt -ge -lt -le -ne

Having said that - however, the documentation does not have information about this function, the following are the appropriate rules for comparing file size:

 RewriteCond expr "filesize('%{REQUEST_FILENAME}') -gt 52428800" RewriteRule ** ** 

Using expressions inside a RewriteCond must be done in this syntax:

 RewriteCond expr "..." 

Bnf

 expr ::= "true" | "false" | "!" expr | expr "&&" expr | expr "||" expr | "(" expr ")" | comp 

You can find the full BNF on the documentation page.

0
source

Obviously .htaccess cannot check the required file size and act accordingly. What you can do is use the External Rewriting Program feature of RewriteMap

First you need to define a RewriteMap , like this, for example, the Apache configuration:

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

Then, inside your .htaccess, define a rule like this by passing:

 RewriteRule - ${checkFileSize:%{REQUEST_FILENAME}} 

%{REQUEST_FILENAME} is passed to the PHP script at STDIN.

Then inside /home/revo/checkFileSize.php you can put the PHP code to check the file size and act accordingly, like redirecting to the URI that the basic auth dialog shows.

+3
source

I would do it in 2 steps:

1: htaccess redirects all requests to a single php script, let's say that you have files inside /test/ and you want everything to be processed /test/index.php , for example:

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

RewriteCond is to avoid loop requests.

2: index.php script executes all auth logic based on the requested file size, for example:

 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 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 ); 

There are many possible improvements, but it should work as a base.

+2
source

I think both answers from @Paolo Stefan and @anubhava are valid (+1).

Please note: using RewriteMap will modify the apache configuration, and not just the .htaccess file. If you think a little about performance, you should essentially put everything in the .htaccess files into the <directory /same/filesystem/path/as/the/.htaccess/file/> directives and put AllowOverride None in the configuration Virtualhost You will of course get some speed by avoiding the I / O files and dynamic check-for-configuration-files settings for apache for each request (.htaccess files are bad, really). Therefore, a problem with RewriteMap is not available in .htaccess should not be a problem.

The theses of the two answers enable you to dynamically change file-based Authentication headers. Now, one important fact that you forgot to mention in your question is that the files are not directly accessible on the same server except PHP, and also that you do not want to run a script for each download.

With the current @anubhava solution, you will have an OS call for the file size at each access, and, of course, this script should be run on the file storage server.

One solution could be storage somewhere (dedicated database or key store)? file size index. You can feed this index after each load, you could manage some asynchronous tasks to maintain it. Then, on the Apache configuration of the file storage server, you will need to run a script check for file sizes. With RewriteMap, you have several options:

  • use a very fast script with the prg: keyword (written in C, Perl, nothing, you are not tied to PHP), querying this file size index in this data store or even fastdbd: to directly execute the SQL query in apache. But this means a request for each request, so you have other solutions.
  • use directly o the mapping file with the txt: keyword txt: having for each file name the already calculated match size, more requests, just
  • even better, use the hashmap of this file with the dbm: `key.

With the last two parameters, the file size index is a text file or a hashed version of this text file. Apache caches the hash map and recalculates the cache on reboot or when the file modification time changes. Thus, you just need to recalculate this hash file after each boot to get a very fast file size check in RewriteRule, as shown in anubhava, but using

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

You can also try using mod_security on file servers and check the Content-Length header to add HTTP authentication. Check out this thread to start answering this question. But mod_security configuration is not an easy task.

+2
source

Not directly, but with a little modification on the file system side, you can do this.

If this is the system that users are loading into, as well as loading, you can turn off the Content-Length header in mod_rewrite to put large files in a separate directory. (or if you can move them in any other way anyway at boot)

Next, in the directory with large files, you set the required auth for all files for it.

Finally, use the existence tests in mod_rewrite to transparently redirect the user to the large_files directory, if there is a file.

If you cannot move files, you can use symbolic links to customize the two layouts.

+1
source

According to this, mod_rewrite supports the "-s" CondPattern, which checks if the specified TestString is a regular file with a non-zero size. The attached patch extends the "-s" to support arbitrary size comparisons.

So the question is:

 CheckIf {REQUESTED_FILE_SIZE} 50 # MB 

should work with this .htaccess code:

 RewriteCond %{REQUEST_FILENAME} -s=52428800 
+1
source

Source: https://habr.com/ru/post/952080/


All Articles