I am doing upload and download script with php. For the upload part, I store the uploaded file, for example, 'my picture.jpg' above my 'htdocs/' with a random name. e.x.:

[-] htdocs
   |--[+] download
  [-] upload
   |--abcdef <<-- 'my picture.jpg' stored as 'abcdef'

The original file name and the new random name is linked by database.

In retrieving the file above, first I create random directory under 'htdocs/download/', copy the file there then rename it back to its original name before handing over the download link.

[-] htdocs
   |--[-] download
       |--[-] zyxwvu
           |--my picture.jpg
  [-] upload         ^
   |--abcdef  ->- copy

For big files, especially with multiple download request, there will be some unnecessary copy of the files.

My question is, how can I request apache to read the file 'upload/abcdef', and give the link as 'download/zyxwvu/my picture.jpg' so it can be downloaded without an extra copy?

Dani AI

Generated

As described, copying large uploads into a temporary htdocs subtree wastes I/O and introduces race conditions. Two practical ways to avoid copying while still serving a filename that looks like the original: (1) let Apache serve the file directly via an internal redirect (fast, low memory), or (2) expose the file with a filesystem link (symlink or hard link) into a temporary download path and remove that link after expiry. 's alias hint points toward permanent mapping; the token + server-side redirect methods below let access be temporary and controlled.

If you can install/enable a small Apache module, use X‑Sendfile (Apache) so your PHP only authorizes the request and tells Apache which file to send. PHP example:

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="my picture.jpg"');
header('X-Sendfile: /path/outside/docroot/abcdef');
exit;

This avoids PHP reading file bytes (so it’s efficient and supports server-level range requests). The module must be enabled and configured to allow that path.

If you can't use X‑Sendfile, stream from PHP in chunks (no copy) and be sure to turn off output buffering and increase max execution time. Basic safe pattern:

$path = '/path/outside/docroot/abcdef';
$fname = 'my picture.jpg';
if (!is_readable($path)) { header('HTTP/1.0 404 Not Found'); exit; }
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($fname) . '"');
header('Content-Length: ' . filesize($path));
$fp = fopen($path, 'rb');
while (!feof($fp)) { echo fread($fp, 8192); flush(); }
fclose($fp);
exit;

If you prefer filesystem links, create a temporary symlink/hard link into htdocs/download/<token>/ and let Apache serve it, then remove the link after the TTL. Example (Linux):

ln -s /path/outside/docroot/abcdef /path/htdocs/download/zyxwvu/my\ picture.jpg

Notes and cautions: always authorize by token stored in your DB (unguessable token + expiry), sanitize the download filename to prevent header injection/path tricks, ensure Apache allows following links, and don’t delete a link while another client may still be downloading—use expiry + periodic cleanup (cron) or track active downloads before unlinking. For Windows use mklink/mklink /H or junctions, remembering Windows link tools and privileges differ from Linux. Recommended: use token+X‑Sendfile where possible, fallback to PHP streaming, and use symlinks only when server config or policies allow.

Recommended Answers

All 5 Replies

Maybe you can use symlinks? if you are on ubuntu though I don't know if that exists on windows

As I read about the symlinks, it converge to the point that i must create the link by script, isnt it? Ill try this one later.

Back to apache, then, is it possible to request the apache itself to read into another location? Because I would like very much to make this task be done by apache itself.

maybe this helps:
this is my virtualhost and as you can see I have all files from a certain dir (/usr/local/www/django/ninv) without copy paste them every time I make a change to that directory =)

<VirtualHost *:81>
    Alias /med /usr/local/www/django/ninv/med/
    Alias /admin-media /usr/local/www/django/ninv/admin/media/
    ServerName localhost
    ServerAdmin d@g.com

    DocumentRoot /usr/local/www/django/ninv/

    <Directory /usr/local/www/django/ninv/>
	Options Indexes FollowSymLinks MultiViews
	AllowOverride None
	Order allow,deny
	allow from all
    </Directory>

    WSGIScriptAlias / /usr/local/wsgi/scripts/django.wsgi

    <Directory /usr/local/wsgi/scripts>
    Order allow,deny
    Allow from all
    </Directory>

</VirtualHost>

hope this helps

you should only look at the documentroot and directory tags

doubled.. See next post.

I dont think i would use that. What I want is for apache to somehow alias the 'abcdef' as 'my picture.jpg' only when that file is requested. The alias should be deleted, say, after 1 hour after last download.

Using virtual directory will allow the files to be accessed anytime, while I store them using different name than the original.

I got the application to make alias for windows by sysinternals: junction. However it can only alias directories, so i would have to store the uploaded file without modifying the name. I've seen some CLI aliasing application but i haven't tested them yet.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.