fasta文件校验

fasta文件校验

最近在利用javascripte构建网页blast时候,涉及到客户端文件和表单的提交。因此结合vue与element-ui框架封装了一个上传并对fasta文件进行校验的插件

1.获取文件对象

  • 使用拖拽事件,移动文件
  • dataTransfer.files获取拖拽文件
1
this.fileData = e.dataTransfer.files[0]

2.读取文件数据

  • 使用FileReader对象读取文件对象内容
  • 作为字符窜进行读取,触发load事件
1
2
3
4
5
var reader = new FileReader()
reader.readAsText(fileData, 'utf-8') // 触发load事件
reader.onload = function () {
reader.result //文件内容
}

3.匹配核酸序列与蛋白序列

创建正则表达式对核酸序列与蛋白序列进行匹配

  • 核苷酸序列,除了A T C G N几种碱基外还有换行符\n
  • i忽略大小写,m多行匹配
1
var Basepattern = /[^ATCGN\n\r]/im // 匹配除这些字符之外的字符
  • 蛋白序列就包含20中氨基酸缩写和换行符
1
var ProteinPattern = /[^GAVLIPFYWSTCMNQDEKRH\\*\r\n]/im
  • 提取核苷序列与蛋白序列,slice忽略第一个空白字符
1
var sequenceArray = reader.result.split(/>[^\n]+\n/).slice(1)
  • 遍历所有序列

只有序列中有一条满足正则表达式,则表示错误的序列格式;并返回true;

而蛋白序列的校验时还多了一条规则,因为蛋白序列都是以甲硫氨酸开头,并且核酸的基因缩写与氨基酸缩写重叠了不能够区分蛋白序列与氨基酸序列

1
2
3
4
5
6
7
BaseFlag = sequenceArray.some((sequence) => {
return Basepattern.test(sequence)
})
ProteinFlag = sequenceArray.some((sequence) => {
return ProteinPattern.test(sequence) || /^[^M]/i.test(sequence)
// 核苷酸序列碱基缩写被氨基酸序列覆盖,所有必须以M氨基酸开头才是蛋白序列
})

4.回调函数获取校验结果

因为onload函数是异步的,所以有可能出现文件还没校验完,客户端状态就已经发生改变;所以使用回调函数获取校验结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
validateFasta(this.fileData, (BaseFlag, ProteinFlag) => {
if (BaseFlag && ProteinFlag) {
this.showModal = true
this.Modalmessage = 'error fasta file'
this.ModalFontColor = { color: '#d63031' }
this.Modalicon = 'el-icon-check'
setTimeout(() => { this.showModal = false }, 1000)
} else if (!BaseFlag) {
this.showModal = true
this.Modalmessage = 'Nucleic acid sequence file'
this.ModalFontColor = { color: '#4cd137' }
this.Modalicon = 'el-icon-close'
setTimeout(() => { this.showModal = false }, 1000)
} else if (!ProteinFlag) {
this.showModal = true
this.Modalmessage = 'Protein sequence file'
this.ModalFontColor = { color: '#4cd137' }
this.Modalicon = 'el-icon-close'
setTimeout(() => { this.showModal = false }, 1000)
}
})

5.校验完成后将数据提交后台

客户端使用FormData对象可以同时提交文件与表单,在后台借助connect-multiparty插件获取上传的文件

  • 将文件数据与表单数据合并
  • 表单数据需要使用for循环进行包装

如果需要获取FormData已经添加的内容,需要使用get方法;因为添加进去的内容已经变成私有变量无法直接访问。

1
2
3
4
5
6
  const formData = new FormData()
formData.append('fastafile', this.$refs.dropfile.fileData)
//包装表单数据
for (var key in this.formInline) {
formData.append(key, this.formInline[key])
}
  • 提交后台
1
2
3
4
5
request.post('/test', formData).then(
() => {
console.log('ok')
}
)

测试过程遇到的跨域问题,使用本地代理服务器与后端API进行交互;因为使用浏览器与后端API交互时,浏览器处于安全原因会阻止跨域请求。

配置vue.config.js配置文件,以及axios的请求地址改成’/api’

1
2
3
4
5
6
7
8
proxy: {
'/api': {
target: 'http://后端地址:80',
ws: true, // 允许跨域
pathRewrite: {
'^/api': '/'
}
}

6.后端获取数据

后台获取数据展示

  • 借助connect-multiparty插件,将文件存在/tmp/目录下
  • 借助body-parse解析form表单数据
1
2
3
4
5
6
7
8
9
10
11
12
var multipart = require('connect-multiparty') //处理上传的文件
var fs = require('fs')

var multipartMiddleware = multipart()
router.post('/test', multipartMiddleware, function (req, rep) {
tmpFilePath = req.files.fastafile.path
console.log(req.files)
var fasta = fs.readFileSync(tmpFilePath, 'utf-8')
console.log(req.body)
console.log(fasta)
rep.send('test')
})

7.演示地址

fasta文件拖拽校验

参考

  1. 文件拖拽失效解决
  2. 读取FileList对象内容
  3. 拖拽事件触发
  4. axios跨域
------ 本文结束 thankyou 感谢阅读 ------

欢迎扫一扫上面的微信二维码,订阅 codeHub 公众号