Galaxy 生信平台(三):xlsx 上传与识别
我在《Firefox Quantum 向左,Google Chrome 向右》中,曾经吐槽过在 Firefox 中使用 Galaxy 上传本地的 Excel 文件时,会出现 xlsx 无法识别异常的问题。今天,我们来聊一聊原因。
背景
关于 Galaxy 生物信息平台,这里就不多说了,感兴趣的可以参考本专栏的前两篇文章。对于数据上传,Galaxy 不仅可以支持 NCBI SRA、EBI SRA、UCSC main table browser 等数据库数据的无缝对接。
![30cbbbaa-5f56-4710-878b-d68e3087df8a.png](https://oscimg.oschina.net/oscnet/30cbbbaa-5f56-4710-878b-d68e3087df8a.png)
在本地文件的上传中,Galaxy 支持包括 ab1、arff、fasta、fastq、xlsx 在内 100 多种常见的格式数据上传。
![b4236be1-25a3-403b-bb11-4f579a191d50.png](https://oscimg.oschina.net/oscnet/b4236be1-25a3-403b-bb11-4f579a191d50.png)
对于不太熟悉命令行操作的科研工作者,Excel 是他们进行批量订单提交和处理最喜欢也是最熟悉的一个数据格式,因此,我们以 Galaxy 为基础开发一部分定制化工具中,有很大的一部分都是基于 excel 文件进行处理的工具。但随之而来的问题是,所有的这些工具在 Google Chrome 下可以运行良好,但是在 Firefox 下却出现了问题。
![a4be5ddb-d9ce-487f-8bec-98ef302a3d04.png](https://oscimg.oschina.net/oscnet/a4be5ddb-d9ce-487f-8bec-98ef302a3d04.png)
xlsx 文件上传
一开始,在办公环境下,我在内网环境部署的 Galaxy 和 https://usegalaxy.org/ 中分别对 xlsx 格式的文件进行上传测试,发现:
在 Chrome 中两个 Galaxy 都能正常上传文件,没有任何错误。
只有在 Firefox 中两个 Galaxy 才会出现如上截图的相同 Warning。
于是,下意识的,我开始怀疑,是不是 Firefox 会针对 Excel 的文件进行了特殊处理?还是 Galaxy 的 xlsx 文件识别存在 bug?针对前一个问题,我一开始并不知道如何去验证,但对于后一个问题,我开始了另外的尝试。
start_cgi_http_server.sh
#!/bin/bash
mkdir ./cgi-bin/
cp upload.cgi ./cgi-bin/
chmod +x ./cgi-bin/upload.cgi
mkdir ./upload/
python -m http.server --cgi 8080
upload.cgi
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cgi, cgitb, os, sys
UPLOAD_DIR = './upload'
def save_uploaded_file():
print 'Content-Type: text/html; charset=UTF-8'
print
print '''
<html>
<head>
<title>Upload File</title>
</head>
<body>
'''
form = cgi.FieldStorage()
if not form.has_key('file'):
print '<h1>Not found parameter: file</h1>'
return
form_file = form['file']
if not form_file.file:
print '<h1>Not found parameter: file</h1>'
return
if not form_file.filename:
print '<h1>Not found parameter: file</h1>'
return
uploaded_file_path = os.path.join(UPLOAD_DIR, os.path.basename(form_file.filename))
with file(uploaded_file_path, 'wb') as fout:
while True:
chunk = form_file.file.read(100000)
if not chunk:
break
fout.write (chunk)
print '<h1>Completed file upload</h1>'
print '''
<hr>
<a href="../upload.html">Back to upload page</a>
</body>
</html>
'''
cgitb.enable()
save_uploaded_file()
upload.html
<html>
<head>
<title>Upload File</title>
</head>
<body>
<h1>Upload File</h1>
<form action="cgi-bin/upload.cgi" method="POST" enctype="multipart/form-data">
File: <input name="file" type="file">
<input name="submit" type="submit">
</form>
</body>
</html>
通过这三个程序,就可以在 Linux 下启动一个简单文件上传小网站。网站效果如下面的截图所示。
xlsx 文件识别
通过 python cgi 上传完文件后,在使用 python 模块进行处理的时,发现通过 Firefox 上传的文件开始出现问题了:
In [1]: import pandas as pd
In [2]: pd.read_excel("upload/upload.xlsx")
---------------------------------------------------------------------------
XLRDError Traceback (most recent call last)
<ipython-input-8-9e85b7330a4e> in <module>
----> 1 pd.read_excel("upload/upload.xlsx")
......
XLRDError: Unsupported format, or corrupt file: Expected BOF record; found b'b\x14#e\xa9\x01W\x00'
于是,开始回去看 Galaxy 的源码,想要搞明白 Galaxy 对于 xlsx 文件上传到底是怎么进行识别的,终于在 packages/data/galaxy/datatypes/binary.py
中发现 Galaxy 正是使用了 python 的 zipfile
模块 :
![0c7cf265-f1d4-446a-beab-a9c7713e1a2c.png](https://oscimg.oschina.net/oscnet/0c7cf265-f1d4-446a-beab-a9c7713e1a2c.png)
zipfile
来对先前 python cgi 上传的文件进行测试:
In [9]: import zipfile
In [10]: zipfile.ZipFile("upload/upload.xlsx")
---------------------------------------------------------------------------
BadZipFile Traceback (most recent call last)
<ipython-input-10-3793f2363956> in <module>
----> 1 zipfile.ZipFile("upload/upload.xlsx")
......
BadZipFile: File is not a zip file
同样的操作,我在 Chrome 重复了一遍,但是却神奇的发现,不管是 panda
还是 zipfile
模块,竟然一切都表现正常!似乎,Firefox 的确有点不正常。
真正原因
针对这个问题,我最开始向 Galaxy Project 团队咨询过,但一直没有从根本解决掉这个问题,他们建议考虑非 xlsx 格式数据的工具开发。
![986d53e8-72f8-4f65-94ee-d4516b28efc4.jpg](https://oscimg.oschina.net/oscnet/986d53e8-72f8-4f65-94ee-d4516b28efc4.jpg)
直到前几天,突发奇想在 Firefox 社区中重新提起这个事情,一个热心网友的回复才让我意识到了问题的所在,也就是哈希——文件完整性校验。
![d20eaf5c-1676-4440-a1a0-da20713bb38c.png](https://oscimg.oschina.net/oscnet/d20eaf5c-1676-4440-a1a0-da20713bb38c.png)
我把文件上传前的 MD5 和文件上传后的 MD5 重新进行了计算比较,这才发现:
使用 Firefox 上传前后文件的 MD5 是一致,Python 却不能识别为有效的 zip 文件;
使用 Chrome 上传的文件前后 MD5 是不一致的,Python 却能正常识别为有效的 zip 文件。
很明显,我的原始 xlsx 文件是有问题的!!吐血中!!!但是在办公环境中,这个原始的 xlsx 文件不管是 Office 2016 还是 WPS 都能正常打开,正常编辑保存。唯一不同的是文件中多了一个锁的标志。
![3669106c-6d07-45cc-8d19-118503de119b.png](https://oscimg.oschina.net/oscnet/3669106c-6d07-45cc-8d19-118503de119b.png)
其实,这就是企业企业办公文档 Office Excel 软件加密的一种效果。
安装加密软件:安装加密服务端和管理端,客户端安装在被加密的电脑中;
设置加密策略:打开管理端,选择文件加密—加密策略,勾选需要加密的 office Excel,然后保存策略,如下图;重启被加密员工电脑。
![90d0f8cb-8777-411c-a2bc-a6917273738d.jpg](https://oscimg.oschina.net/oscnet/90d0f8cb-8777-411c-a2bc-a6917273738d.jpg)
测试加密效果:被加密电脑重启后,打开 word 文档,新建文档并编辑保存,保存后的文件会显示“加锁”标志,如下图示,显示已成功加密。
![e312c2e9-42cb-4d5c-a227-35d4a9a49301.jpg](https://oscimg.oschina.net/oscnet/e312c2e9-42cb-4d5c-a227-35d4a9a49301.jpg)
实现效果:员工编辑后的文档自动加密,加密后的文档未经许可,私自通过 QQ,电子邮件,U盘等任何方式传输到公司以外,都将无法打开使用;不改变编辑操作习惯,在企业内部相互流通编辑,不受影响。彻底从源头保障数据的安全性。此外还可实现如需外发文件,可通过申请解密流程授权解密后方可外发;同时还可对其他软件进行加密,比如办公软件,设计软件,工程软件,编程软件,研发软件等。
最后,把未加密的 xlsx 文件进行重新测试,一切问题迎刃而解。
总结一下
这是一个企业文档加密引发的填坑记录,从问题的发现,问题的思考,到解决的思路值得探讨记录一下。
MD5,MD5,MD5,重要的事情要说三遍!!!
学习源码,Galaxy Project 的源码挺有意思的,不妨一读。
Python CGI 的一些简单应用,也挺好玩。
多多交流,学会搜索,善用资源,事半功倍。
Chrome 为什么能绕开部分企业文档加密的枷锁,还原文件,这是一个有待后面学习的问题,mark 一下,同时期待大家指点迷津。
本文分享自微信公众号 - 生信科技爱好者(bioitee)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。