You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Python HTTP Server实现GET请求下载指定文件?

Got it, let's add the file download functionality to your existing HTTP server. Here's the modified code with clear explanations:

import cgi
import os
from urllib.parse import urlparse, parse_qs
from http.server import BaseHTTPRequestHandler, HTTPServer

class S(BaseHTTPRequestHandler):
    def _set_headers(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def _html(self, message):
        content = f"<html><body><h1>{message}</h1></body></html>"
        return content.encode("utf8")

    def do_GET(self):
        # Parse the request URL to extract query parameters
        parsed_url = urlparse(self.path)
        query_params = parse_qs(parsed_url.query)
        
        # Check if a filename is provided in the GET request
        if 'filename' in query_params:
            filename = query_params['filename'][0]
            
            # Validate the file exists and is a regular file
            if not os.path.exists(filename):
                self.send_error(404, f"File '{filename}' not found on server")
                return
            if not os.path.isfile(filename):
                self.send_error(400, f"'{filename}' is not a valid file")
                return
            
            try:
                # Read the file content in binary mode
                with open(filename, 'rb') as file:
                    file_content = file.read()
                
                # Set headers to trigger file download
                self.send_response(200)
                self.send_header('Content-Type', 'application/octet-stream')
                self.send_header('Content-Disposition', f'attachment; filename="{os.path.basename(filename)}"')
                self.send_header('Content-Length', str(len(file_content)))
                self.end_headers()
                
                # Send the file content to the client
                self.wfile.write(file_content)
                return
            except Exception as e:
                self.send_error(500, f"Error accessing file: {str(e)}")
                return
        
        # Default GET behavior: return the "hi!" message
        self._set_headers()
        self.wfile.write(self._html("hi!"))

    def do_HEAD(self):
        self._set_headers()

    def do_POST(self):
        form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD':'POST',
                     'CONTENT_TYPE':self.headers['Content-Type'],
                     })
        filename = form['file'].filename
        data = form['file'].file.read()
        open(filename, "wb").write(data)
        self._set_headers()
        self.wfile.write(self._html("hi!"))

# Example to start the server (you can adjust port as needed)
if __name__ == "__main__":
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, S)
    print('Server running on port 8000...')
    httpd.serve_forever()

Key Changes Explained:

  • Query Parameter Parsing: We use urlparse and parse_qs to pull the filename parameter from the GET request URL (e.g., http://localhost:8000/?filename=my_uploaded_file.txt).
  • File Validation: We check if the requested file exists and is a regular file (not a directory) to avoid serving unintended content or throwing errors.
  • Download Headers:
    • Content-Type: application/octet-stream tells the browser this is a binary file meant for download.
    • Content-Disposition: attachment forces the browser to show a download prompt instead of trying to display the file directly.
    • Content-Length provides the file size to the browser for progress tracking.
  • Error Handling: We send meaningful HTTP error codes (400 for invalid requests, 404 for missing files, 500 for server issues) to help clients understand what went wrong.

Important Security Note:

Right now, the server will serve any file it has access to on the system, which could let attackers access sensitive files via path traversal (e.g., filename=../secret.txt). To fix this, restrict file access to a specific directory:

# Define a safe directory for uploads/downloads
ALLOWED_DIR = os.path.abspath("./safe_files")

# In do_GET, add this check before accessing the file
file_path = os.path.abspath(filename)
if not file_path.startswith(ALLOWED_DIR):
    self.send_error(403, "Access denied: file is outside allowed directory")
    return

Make sure to update your POST handler to save files into this same ALLOWED_DIR too!

内容的提问来源于stack exchange,提问作者user12813016

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 13:47:29