我在《Firefox Quantum 向左,Google Chrome 向右中,曾经吐槽过在 Firefox 中使用 Galaxy 上传本地的 Excel 文件时,会出现 xlsx 无法识别异常的问题。今天,我们来聊一聊原因。

背景

关于 Galaxy 生物信息平台,这里就不多说了,感兴趣的可以参考本专栏的前两篇文章。

对于数据上传,Galaxy 不仅可以支持 NCBI SRA、EBI SRA、UCSC main table browser 等数据库数据的无缝对接。


在本地文件的上传中,Galaxy 支持包括 ab1、arff、fasta、fastq、xlsx 在内 100 多种常见的格式数据上传。


对于不太熟悉命令行操作的科研工作者,Excel 是他们进行批量订单提交和处理最喜欢也是最熟悉的一个数据格式,因此,我们以 Galaxy 为基础开发一部分定制化工具中,有很大的一部分都是基于 excel 文件进行处理的工具。但随之而来的问题是,所有的这些工具在 Google Chrome 下可以运行良好,但是在 Firefox 下却出现了问题。


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 模块 :


于是,我也开始使用 
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 格式数据的工具开发。


直到前几天,突发奇想在 Firefox 社区中重新提起这个事情,一个热心网友的回复才让我意识到了问题的所在,也就是哈希——文件完整性校验。


我把文件上传前的 MD5 和文件上传后的 MD5 重新进行了计算比较,这才发现:

  • 使用 Firefox 上传前后文件的 MD5 是一致,Python 却不能识别为有效的 zip 文件;

  • 使用 Chrome 上传的文件前后 MD5 是不一致的,Python 却能正常识别为有效的 zip 文件。

很明显,我的原始 xlsx 文件是有问题的!!吐血中!!!但是在办公环境中,这个原始的 xlsx 文件不管是 Office 2016 还是 WPS 都能正常打开,正常编辑保存。唯一不同的是文件中多了一个锁的标志。


其实,这就是企业企业办公文档 Office Excel 软件加密的一种效果。

  1. 安装加密软件:安装加密服务端和管理端,客户端安装在被加密的电脑中;

  2. 设置加密策略:打开管理端,选择文件加密—加密策略,勾选需要加密的 office Excel,然后保存策略,如下图;重启被加密员工电脑。


测试加密效果:被加密电脑重启后,打开 word 文档,新建文档并编辑保存,保存后的文件会显示“加锁”标志,如下图示,显示已成功加密。


实现效果:员工编辑后的文档自动加密,加密后的文档未经许可,私自通过 QQ,电子邮件,U盘等任何方式传输到公司以外,都将无法打开使用;不改变编辑操作习惯,在企业内部相互流通编辑,不受影响。彻底从源头保障数据的安全性。此外还可实现如需外发文件,可通过申请解密流程授权解密后方可外发;同时还可对其他软件进行加密,比如办公软件,设计软件,工程软件,编程软件,研发软件等。

最后,把未加密的 xlsx 文件进行重新测试,一切问题迎刃而解。

总结一下

这是一个企业文档加密引发的填坑记录,从问题的发现,问题的思考,到解决的思路值得探讨记录一下。

  • MD5,MD5,MD5,重要的事情要说三遍!!!

  • 学习源码,Galaxy Project 的源码挺有意思的,不妨一读。

  • Python CGI 的一些简单应用,也挺好玩。

  • 多多交流,学会搜索,善用资源,事半功倍。

Chrome 为什么能绕开部分企业文档加密的枷锁,还原文件,这是一个有待后面学习的问题,mark 一下,同时期待大家指点迷津。

本文分享自微信公众号 - 生信科技爱好者(bioitee)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

Galaxy 生信平台(三):xlsx 上传与识别的更多相关文章

  1. SNF开发平台WinForm之六-上传下载组件使用-SNF快速开发平台3.3-Spring.Net.Framework

    6.1运行效果: 6.2开发实现: 1.先在要使用的项目进行引用,SNF.WinForm.Attachments.dll文件. 2.在工具箱内新建选项卡->选择项,浏览找到文件SNF.WinFo ...

  2. 解决Windows平台通过cURL上传APP到蒲公英pgyer平台时无法使用中文升级描述的问题

    解决Windows平台通过cURL上传APP到蒲公英pgyer平台时无法使用中文升级描述的问题 官方上传命令 curl -F file=@"315.apk" -F uKey=XXX ...

  3. 三种上传文件不刷新页面的方法讨论:iframe/FormData/FileReader

    发请求有两种方式,一种是用ajax,另一种是用form提交,默认的form提交如果不做处理的话,会使页面重定向.以一个简单的demo做说明: html如下所示,请求的路径action为"up ...

  4. 三 : spring-uploadify上传文件

    一 : applicationContext.xml中:必须声明不然获取不到<!-- 上传文件的配置 --> <bean id="multipartResolver&quo ...

  5. upload三种上传方式(上)---Servlet---post---commons-fileupload.1.2.1.jar方式请求上传文件

    上传前进行的配置选项: 1.在下方的Servers中,右键你的tomcat--open,选中下面两个配置. 第一个:Serve modules without publishing 作用:tomcat ...

  6. Windows操作系统远程Linux服务器传输文件方法(以EasyDSS云平台、EasyNVR上传部署为例)

    本文转自博客:https://blog.csdn.net/black_3717/article/details/79769406 问题背景: 之前给客户部署我们一款EasyDSS云平台(配合EasyN ...

  7. jQuery插件之路(三)——文件上传(支持拖拽上传)

    好了,这次咱一改往日的作风,就不多说废话了,哈哈.先贴上源代码地址,点击获取.然后直接进入主题啦,当然,如果你觉得我有哪里写的不对或者欠妥的地方,欢迎留言指出.在附上一些代码之前,我们还是先来了解下, ...

  8. web自动化之selenium(三)文件上传

    1.上传标签为input #若上传文件的标签为<input>可以直接定位标签,然后send_keys(文件路径)可以直接上传 2.利用第三方软件Autoit上传 1.下载Autoit:ht ...

  9. SpringBoot2.0(三) 文件上传

    SpringBoot中发起文件上传示例: /** * 文件上传 * @param multipartFile * @param path * @return */ @RequestMapping(va ...

  10. Struts2学习(三)上传下载

    今天记录一下利用struts2实现上传下载,借此案例说明一下struts2的开发流程. 须要注意的是struts2版本号不同非常多地方的写法是不同的.本例使用struts2.3.15 .有差别的地方文 ...

随机推荐

  1. Spring 依赖注入有哪几种方式

    1. 构造器注入 /*带参数,方便利用构造器进行注入*/   public CatDaoImpl(String message){               this. message = mess ...

  2. Spring Data Redis 框架

    系统性学习,移步IT-BLOG 一.简介 对于类似于首页这种每天都有大量的人访问,对数据库造成很大的压力,严重时可能导致瘫痪.解决方法:一种是数据缓存.一种是网页静态化.今天就讨论数据缓存的实现 Re ...

  3. Quicker快速开发,简单的网页数据爬取(示例,获取天眼查指定公司基础工商数据)

    前言 有某个线上项目,没有接入工商接口,每次录入公司的时候,都要去天眼查.企查查或者其他公开数据平台,然后手动录入,一两个还好说,数量多了的重复操作就很烦,而且,部分数据是包含超链接,一不注意就点进去 ...

  4. 主板芯片组驱动和Win系统版本互相关联

    主板芯片组驱动和Win系统版本互相关联,过早的系统安装较新版的芯片组驱动,或者较新版本的操作系统安装旧版的芯片组驱动,都可能导致系统不稳定蓝屏.解决方案就是安装最新的芯片组驱动和最新版的操作系统.

  5. 设置Mysql sort_buffer_size参数

    按照官网的解释:Each session that must perform a sort allocates a buffer of this size. sort_buffer_size is n ...

  6. ACM-NEFUOJ-汉诺塔问题

    P200汉诺塔 #include<bits/stdc++.h> using namespace std; int main() { int n,i; long long s[40]; s[ ...

  7. DevOps, HybridOps and AIOps浅谈

    DevOps, HybridOps and AIOps浅谈 DevOps的概念出现比较久了,很多的IT项目也都在实际的运用中.AIOps概念作为DevOps的升级版,也得到了很广大的关注,也出现了很多 ...

  8. 最简单Openwrt ipv6配置,局域网WAN6中继模式获取原生ipv6地址

    条件 condition wan 和 wan6 是默认配置     Wan and wan6 are the default configurations 同时wan6可以获取到原生IPv6     ...

  9. 无法加载 DLL“xxxx.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。

    有一台服务器在执行接口的时候遇到了这样一个问题: 其他服务器上都没有这个问题,IIS部署好的项目目录的bin文件夹下是有这个dll的,但却提示无法加载,在网上找了好多帖子,终于发现了问题. 首先用De ...

  10. 移除List的统一逻辑写法 LeetCode 203

    原理:通过创建一个新的结点,放在头结点的前面,作为真正头结点的前驱结点,这样头结点就成为了意义上的非头结点,这样就可以统一操作结点的删除操作. 需要注意的是:这个新的结点是虚拟头结点,真的的头结点依然 ...