文件托管程序开发:如何让指定目录下php/py文件显示为文本或可下载?
Got it, let's work through this for your file hosting app. You’ve got two solid approaches here—one using web server config (great if you’re running Apache or Nginx) and another building custom logic directly into your backend (perfect if you want full control over the user experience):
This is a quick fix if you don’t want to write tons of custom code. The key is disabling automatic execution of PHP/Python files and adding a way to toggle between viewing as text and downloading.
Apache Setup
Create a .htaccess file in your target directory, then add these rules to route PHP/PY requests to a handler script:
# Disable PHP execution for this directory (critical to prevent code runs) php_flag engine off # Enable rewrite rules RewriteEngine On # Only process actual files with .php/.py extensions RewriteCond %{REQUEST_FILENAME} -f RewriteCond %{REQUEST_URI} \.(php|py)$ # Route to our handler script RewriteRule ^(.*)$ file_handler.php?file=$1 [L]
Next, create file_handler.php in the same directory to handle the view/download logic:
<?php // Lock down the allowed directory (update this to your target path!) $allowed_dir = realpath(__DIR__); $requested_file = $_GET['file'] ?? ''; $file_path = realpath($allowed_dir . '/' . $requested_file); # Block path traversal attacks (never skip this!) if (strpos($file_path, $allowed_dir) !== 0 || !file_exists($file_path)) { http_response_code(403); exit("Access denied: Invalid file request"); } # Validate file type $file_ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION)); if (!in_array($file_ext, ['php', 'py'])) { http_response_code(400); exit("Invalid file type"); } # Handle user choice if (isset($_GET['download'])) { # Trigger download header('Content-Disposition: attachment; filename="' . basename($file_path) . '"'); } else { # Show as plain text header('Content-Type: text/plain'); } # Output the file content readfile($file_path); ?>
Now users can:
- View the file as text:
yourdomain.com/target-dir/script.php - Download the file:
yourdomain.com/target-dir/script.php?download=1
Nginx Setup
Edit your Nginx server block to disable PHP execution for the target directory and route requests to the same file_handler.php above:
location /target-dir/ { # Disable PHP processing for this directory fastcgi_pass off; # Route PHP/PY files to our handler location ~* \.(php|py)$ { try_files $uri /target-dir/file_handler.php?file=$uri; # Make sure to point to your PHP-FPM socket if needed fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
Adjust the paths and PHP-FPM socket version to match your server setup.
If you’re building your own file hosting app (e.g., with PHP or Python), here’s how to add this functionality directly into your code.
Python Flask Example
from flask import Flask, send_file, abort, request import os app = Flask(__name__) # Define your allowed directory (hardcode this or load from config) ALLOWED_DIR = "/absolute/path/to/your/target/directory" @app.route('/files/<path:filename>') def serve_file(filename): file_path = os.path.join(ALLOWED_DIR, filename) # Block path traversal attacks if not os.path.abspath(file_path).startswith(os.path.abspath(ALLOWED_DIR)) or not os.path.isfile(file_path): abort(403, description="Access denied: Invalid file request") # Validate file extension file_ext = os.path.splitext(filename)[1].lower() if file_ext not in ['.php', '.py']: abort(400, description="Only PHP/Python files are allowed") # Check if user wants to download if request.args.get('download'): return send_file(file_path, as_attachment=True) else: return send_file(file_path, mimetype='text/plain') if __name__ == '__main__': app.run(debug=False) # Disable debug in production!
Key Security Reminders
- Never skip path validation: Attackers will try to access files outside your target directory (e.g.,
../../etc/passwd)—the checks in both examples block this. - Restrict file types: Only allow the extensions you need (PHP/PY) to avoid exposing sensitive files.
- Disable execution: Make sure your server doesn’t run the PHP/PY files directly—always serve them as plain text unless you explicitly want execution (which you don’t here).
内容的提问来源于stack exchange,提问作者user9148619

