背景
在用例管理平台上可以编辑Excel用例文件,但如果上传了合并单元格的Excel用例文件,编辑时候处理起来会无法判断如何去拆解单元格,最终解决方式是:禁止上传存在合并单元格的Excel文件。(那么就需要在上传的时候校验文件中是否存在合并单元格。)
通过网上的资料查询了下,实现方案就是通过 sheet.merged_cells
来解决该问题,核心代码如下:
1 | workbook = xlrd.open_workbook(r'py.xlsx') |
PS: 本文主要是记录下过程中遇到的问题以及一些扩展。
问题
问题1: 后端报错:expected str, bytes or os.PathLike object, not FileStorage
由于文件是直接通过前端上传的,所以传到后端是一个 FileStorage
对象,通过上述方式实现会直接报错。如果仅仅是简单的通过 file_storage.read()
转换成 bytes 后,仍然会有其他新的报错(embedded null byte
)。
最终使用如下方案来进行解决(因为后端原本都是使用 Pandas
库去处理Excel文件的):
1 | book = openpyxl.load_workbook(case_file) |
验证了下,在上传带有单元格的文件时,会触发异常,正准备高高兴兴码完代码休息下~( ̄▽ ̄~)(~ ̄▽ ̄)~ 。然而出于基本的开发素质,我又验证了不带单元格的文件。然而打脸总是来的这么突然。。。😭。
上传失败,后端返回错误 OSError: [Errno 22] Invalid argument
。(事实再次证明:不要以为功能简单就不验证( ̄ε  ̄) 。。。老铁,来吧!继续撸袖子修BUG。)
问题2: OSError: [Errno 22] Invalid argument
通过本地调试,发现触发异常的位置在文件被上传保存后,再次去读取该文件内容的时候。抛错的代码为:
1 | f = pd.ExcelFile(file_abs_path) |
看了下文件的剧对路径,确定文件是存在的,然后去下载下来打开时,提示文件打开遇到错误。。。(并且此时的文件大小小于实际文件的大小,原文件17KB,上传后的文件12KB)。
通过一步步的调试,发现罪魁祸首在于 openpyxl.load_workbook(case_file)
,该操作会直接对传入的 FileStorage 对象进行操作,导致文件内容变化。
1 | # 原数据 case_file.read() 大小为16804,处理后case_file.read() 大小为11528 |
最终解决方案则是:在问题1的代码块后, 新增代码:case_file.stream.seek(0)
即可,通过将原 FileStorage
对象缓存里面的内容指向最初的位置即可。
问题3: xlrd.biffh.XLRDError: File size is 0 bytes
在获得最终解决方案的过程之前,还遇到了问题3,因为 FileStorage 对象在内存中的内容已经被拿出来操作了,实际缓存中的数据大小变成了0,导致了上述的报错。(参考链接),如下是对于 FileStorage 对象的一个注解。
1 | from werkzeug.datastructures import FileStorage |
总结
通过上述一系列的骚操作(瞎折腾)后,终于完成了最初的需求。。。╮(╯Д╰)╭ ,因为过程中很多奇奇怪怪得报错导致整个过程还是挺艰辛的。
⚠️ 心得:大多数时候都是网上直接搜了解决方案,但是由于基础不扎实,在进行实施的时候,各种坑就埋在你脚下了。。。有些时候需要更多的去思考或者了解为什么使用这个方案,以及询问自己更多次为什么会出现这个问题,而不仅仅是解决。