我在《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. 杂谈--User Story

    本篇用于给自己后续慢慢看,对敏捷感兴趣的小伙伴,可以自行去看官方文档或者各种网站的视频讲解,更详细. 对于敏捷开发来说,User Story是开发的基础,把原本需求拆成最小粒度的Story,以方便拆分 ...

  2. VUE百度地图API调用(手机端、PC端、微信通用)

    百度地图API-示例中心: https://lbsyun.baidu.com/jsdemo.htm#aCreateMap 1.引入百度地图(此处用到的是V2.0版本) 1> 建立一个js文件,例 ...

  3. mongo操作数据库

    1.回顾 2.node + mongodb 2.1 安装mongodb 项目中既可以使用mongodb,但是推荐使用mongoose cnpm i mongoose@4 -S 2.2 连接数据库 一定 ...

  4. STM32F407 学习 (0) 各种外设功能 (上)

      本文对正点原子STM32F4探索者的基本功能及外设作最基本的介绍,随笔者本人的学习进程(基本按照正点原子)而不定时更新,起到总结的作用. 一.HAL库编写程序的运行逻辑   HAL库函数(如stm ...

  5. ML - Regression

    Regression Machine Learning 机器学习的意义就在于让机器具备找一个函数(function)的能力 Different types of Functions Regressio ...

  6. FreeSWITCH的originate命令解析及示例

    FreeSWITCH版本:1.10.9 操作系统:CentOS 7.6.1810 originate经常用于发起呼叫,在实际工作过程中用到的也比较多,今天总结下基本用法,也方便我以后查阅. 一.wik ...

  7. pysimplegui之tiee实例(附带github仓库地址)

    今天想写一个文件管理器,结果整了一下午,还是自己看的源代码少,分析别人代码少,最终还是看别人代码才找到错误原因.#!/usr/bin/env python import sys import os i ...

  8. pandas之sql操作

    我们知道,使用 SQL 语句能够完成对 table 的增删改查操作,Pandas 同样也可以实现 SQL 语句的基本功能.本节主要讲解 Pandas 如何执行 SQL 操作.首先加载一个某连锁咖啡厅地 ...

  9. Spring注解系列——@PropertySource

    在Spring框架中@PropertySource注解是非常常用的一个注解,其主要作用是将外部化配置解析成key-value键值对"存入"Spring容器的Environment环 ...

  10. 2.自定义@Excel注解实现数据Excel形式导入导出

    前言 这几天在学习如何使用自定义注解实现Excel格式数据导入导出,参考的还是若依框架里面的代码,由于是初学,所以照猫画虎呗,但是难受的是需要复制并根据自己项目修改作者自定义的工具类以及导入这些工具类 ...