When serving text files through Apache, browsers typically display the content directly rather than triggering a download prompt. This behavior applies to common text formats like .txt, .csv, .json, and others with recognizable MIME types. For web applications where file downloads are preferred over inline viewing, we need server-side intervention.
The most straightforward approach uses Apache's mod_headers
to inject Content-Disposition headers. Here's a complete virtual host configuration example:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/textfiles
<Directory /var/www/textfiles>
Header set Content-Disposition "attachment"
# Alternative for dynamic filename matching:
# Header edit Content-Disposition "^$" "attachment; filename=\"%f\""
</Directory>
</VirtualHost>
For more granular control, you can target specific file extensions using FilesMatch
:
<FilesMatch "\.(txt|csv|json|log)$">
ForceType application/octet-stream
Header set Content-Disposition "attachment; filename=\"%f\""
</FilesMatch>
When working with complex directory structures, consider these approaches:
# For files in specific subdirectories
<DirectoryMatch "/var/www/(downloads|exports)/.*">
Header set Content-Disposition "attachment"
</DirectoryMatch>
# For files with numeric names (e.g., report_123.txt)
<FilesMatch "[0-9]+\.txt$">
Header set Content-Disposition "attachment"
</FilesMatch>
After implementing these changes:
- Run
sudo apachectl configtest
to verify syntax - Reload Apache:
sudo systemctl reload apache2
- Test with curl:
curl -I http://yoursite.com/example.txt
For shared hosting environments where you can't modify the main config:
# In the text files directory's .htaccess
<IfModule mod_headers.c>
<FilesMatch "\.(txt|text)$">
Header set Content-Disposition "attachment"
</FilesMatch>
</IfModule>
While these solutions work well, be aware that:
- Header manipulation adds slight processing overhead
- Complex regex patterns in FilesMatch may impact performance
- Caching behavior might change with forced downloads
When serving files via Apache, browsers typically display text-based files (like .txt, .csv, or .log) directly in the browser window. However, there are cases where you want users to download these files instead. This is where the Content-Disposition
header comes into play.
The most straightforward way to implement this is using Apache's Header
directive in your configuration:
Header set Content-Disposition "attachment; filename=\"%f\""
This configuration will:
- Match files with .txt, .log, or .csv extensions
- Set the Content-Disposition header to "attachment"
- Include the original filename using the %f variable
If you want to apply this to a specific directory (as mentioned in your example), you can use:
Header set Content-Disposition "attachment; filename=\"%f\""
For more complex scenarios where you want to conditionally force downloads, you can combine mod_rewrite with environment variables:
RewriteEngine On
RewriteCond %{QUERY_STRING} download=1
RewriteRule \.(txt|log|csv)$ - [E=FORCE_DOWNLOAD:1]
Header set Content-Disposition "attachment; filename=\"%f\""
This allows you to control downloads via URL parameters (e.g., file.txt?download=1
).
On Debian systems, you'll typically want to place these configurations in either:
- The virtual host configuration in
/etc/apache2/sites-available/
- A .htaccess file in your target directory (if AllowOverride is enabled)
Remember to enable the headers module if it's not already active:
sudo a2enmod headers
sudo systemctl restart apache2
After implementing these changes, verify the headers are being set correctly using curl:
curl -I http://yourserver.com/example.txt
You should see a response header containing:
Content-Disposition: attachment; filename="example.txt"