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

Python CGI脚本实现文件下载后文件显示0字节问题求助

问题根因排查与修复方案

核心错误点

  • 文件路径错误:原代码中with open打开的是当前工作目录下的filename,而非存放在cgi-bin/tmp目录下的目标文件,读取不到有效内容导致输出为空
  • 输出方式错误:使用print函数输出二进制文件内容,会自动追加换行符、触发编码转换,破坏文件结构,甚至直接输出空内容
  • 冗余无效代码:原代码中打开fullpath文件后从未使用也未关闭,属于无效逻辑
  • HTML逻辑冲突:同时设置了表单提交逻辑和a标签直接下载逻辑,两者互斥,a标签跳转不会触发CGI脚本执行,如果tmp目录不可公开访问会直接返回404或空内容
  • 缺少参数校验与文件存在性判断:未校验参数是否存在、文件是否可读,遇到异常情况直接输出空内容

修复后的代码

1. download_file.py 修正版

import cgi, os, sys
form = cgi.FieldStorage()

# 读取文件名参数,异常兜底
filename = form.getfirst('fname', '')
if not filename:
    print("Content-Type: text/html; charset=utf-8")
    print("")
    print("参数错误:未指定文件名")
    exit()

# 拼接正确的目标文件路径
file_path = os.path.join('cgi-bin', 'tmp', filename)
# 校验文件存在性
if not os.path.exists(file_path) or not os.path.isfile(file_path):
    print("Content-Type: text/html; charset=utf-8")
    print("")
    print("错误:请求的文件不存在")
    exit()

# 输出标准下载HTTP头
print('Content-Type: application/octet-stream')
print(f'Content-Disposition: attachment; filename="{filename}"')
print(f'Content-Length: {os.path.getsize(file_path)}')
print("")
# 刷新缓冲区确保HTTP头优先输出
sys.stdout.flush()

# 直接输出二进制文件流
with open(file_path, 'rb') as f:
    sys.stdout.buffer.write(f.read())

2. HTML部分修正(走CGI下载逻辑)

移除冲突的a标签,改用表单提交触发CGI下载:

html += """
            <form action = "download_file.py" method = "get" class='file'>
                <h3>%s</h3>
                <h4>File name: %s</h4>
                <input type='hidden' value="%s" name='fname'>
                <button type="submit" class='btn btn-info'>Download File</button>
            </form>
        """ % (str(i+1), str(files[i]['name']), str(files[i]['name']))

额外注意事项

  • CGI脚本需要有读取cgi-bin/tmp目录下文件的权限,目录权限设置为755、文件权限设置为644即可
  • 如果你选择直接用a标签静态下载,需要将tmp目录移动到web服务器的静态资源根目录,不要放在cgi-bin目录下,避免web服务器拦截静态资源请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:18:02