Flask中无法读取POST请求传来的Excel文件问题排查
问题:AngularJS上传Excel到Flask解析时出现BadZipFile错误
尝试从AngularJS前端发送Excel文件到Flask应用并解析列,遇到以下错误:
File "/var/task/pandas/util/_decorators.py", line 296, in wrapper return func(*args, **kwargs) File "/var/task/pandas/io/excel/_base.py", line 304, in read_excel io = ExcelFile(io, engine=engine) File "/var/task/pandas/io/excel/_base.py", line 867, in __init__ self._reader = self._engines[engine](self._io) File "/var/task/pandas/io/excel/_openpyxl.py", line 480, in __init__ super().__init__(filepath_or_buffer) File "/var/task/pandas/io/excel/_base.py", line 351, in __init__ self.book = self.load_workbook(filepath_or_buffer) File "/var/task/pandas/io/excel/_openpyxl.py", line 491, in load_workbook return load_workbook( File "/mnt/accesspoint/openpyxl/reader/excel.py", line 315, in load_workbook reader = ExcelReader(filename, read_only, keep_vba, File "/mnt/accesspoint/openpyxl/reader/excel.py", line 124, in __init__ self.archive = _validate_archive(fn) File "/mnt/accesspoint/openpyxl/reader/excel.py", line 96, in _validate_archive archive = ZipFile(filename, 'r') File "/var/lang/lib/python3.8/zipfile.py", line 1269, in __init__ self._RealGetContents() File "/var/lang/lib/python3.8/zipfile.py", line 1364, in _RealGetContents raise BadZipFile("Bad magic number for central directory") zipfile.BadZipFile: Bad magic number for central directory
同时尝试用with open(file, 'rb') as f读取文件时,触发错误:TypeError: expected str, bytes or os.PathLike object, not FileStorage
相关代码
AngularJS HTML代码
<nz-card nzTitle="Upload File" bordered={false} style="flex: 1 1 auto;"> <nz-upload [nzCustomRequest]="handleUpload" [(nzFileList)]="fileList" (nzChange)="handleChange($event)" [nzDownload]="handleDownload" [nzAccept]="fileType" > <p class="ant-upload-drag-icon"><i nz-icon nzType="inbox"></i></p> <p class="ant-upload-text"> Click or drag CSV/Excel a file to this area to upload </p> </nz-upload> </nz-card>
AngularJS组件代码
handleUpload = (item: any) => { const formData = new FormData(); formData.append(item.name, item.file); var upload = this.httpClient.post(this.SERVER_URL, formData).subscribe( (res) => { console.log("success"); item.onSuccess(item.file); if (typeof (res) === 'object') { console.log(res); } item.file; }, (err) => { console.log("failure") item.onError(err, item.file); } ) }
Flask Python代码
def upload(): file = request.files['file'] print("request", file) df = pd.read_excel(file, index_col=0, engine='openpyxl') print(df)
错误前日志
request <FileStorage: 'sample_excel.xlsx' ('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')>
原因分析
- FormData键名不匹配:前端用
formData.append(item.name, item.file)添加文件,但后端通过request.files['file']获取,若item.name不是'file',后端实际获取的文件内容为空或无效,导致pandas读取时无法识别为有效的Zip格式(xlsx本质是压缩包)。 - FileStorage对象使用错误:Flask的
FileStorage是类文件对象,不能直接作为路径传给open()函数,需要通过文件流或保存为本地文件来处理。
解决方案
修正前端FormData键名
确保前端FormData的键名和后端获取的键名一致,修改AngularJS组件代码:handleUpload = (item: any) => { const formData = new FormData(); // 明确指定键名为'file',和后端request.files['file']对应 formData.append('file', item.file); var upload = this.httpClient.post(this.SERVER_URL, formData).subscribe( (res) => { console.log("success"); item.onSuccess(item.file); if (typeof (res) === 'object') { console.log(res); } }, (err) => { console.log("failure") item.onError(err, item.file); } ) }后端正确处理FileStorage对象
方案一:直接读取文件流(需重置文件指针到开头)def upload(): file = request.files['file'] # 重置文件指针到起始位置,避免因文件指针偏移导致读取空内容 file.seek(0) df = pd.read_excel(file, index_col=0, engine='openpyxl') print(df)方案二:先保存文件再读取
def upload(): file = request.files['file'] # 将文件保存到本地临时路径 file.save('temp_upload.xlsx') df = pd.read_excel('temp_upload.xlsx', index_col=0, engine='openpyxl') print(df)额外检查项
- 确认上传的Excel文件未损坏,可手动打开验证有效性;
- 确保Angular发送请求时,HttpClient自动设置了
Content-Type: multipart/form-data(发送FormData时会自动处理,无需手动添加)。
内容的提问来源于stack exchange,提问作者teleluck
相关产品推荐
相关产品推荐

