实战篇 - node.js后台实现压缩文件获取、解析并上传至云平台(附源码)

3,598 阅读1分钟

前言

因项目需要,后台需要支持接收前端的压缩文件并解析上传至云平台,一顿踩坑之后基本跑通了整条流程,下面写下来分享给那些像我一样的node小白~

实现过程

安装依赖

本次实现中依赖了node解压模块unzip

yarn add unzip

接收zip文件

之前在网上找了好多资料,基本上都是在服务器本地对各种文件进行操作,难道就没有从前端向后台传、解析压缩文件的先例嘛???

所以,直接从前端把zip文件抛过来,get!

项目UI是基于antd实现的,所以直接用Upload组件进行的上传,这里有个坑要踩,在默认设置下组件上传会报错:No 'Access-Control-Allow-Origin' header is present on the requested resource. 需要给组件设置属性headers= {{ 'X-Requested-With':null }}

get是get到了,但通过fs.createReadStream()来直接读取拿到的buffer是总是回报这样那样的错误,经过一番苦苦搜寻,找到了这样一种解释:This means the library would like to do its own reading of the file rather than being given a stream of bytes for analysis.,大概意思就是node的方法希望接收的资源是资源的路径而不是资源本身,既然这样,那就把从前端获取的数据先存起来好了:

    fs.writeFile(`${__dirname}/temp/temp.zip`, z, function(e) {
        ···//这里的z就是从前端拿来的资源
    }

这下就可以拿到想要的zip了吧,然后就可以为所欲为了。

    fs.writeFile(`${__dirname}/temp/temp.zip`, z, function(e) {
        fs.createReadStream(`${__dirname}/temp/temp.zip`) //拿到zip
          .pipe(unzip.Parse()) //将流流入unzip.Parse
          .on('entry', function(entry: any) {
                let fileName = entry.path.replace(/[\w]+\//g, '').trim() // 将路径上的目录都剔除掉,只留下文件名
                if ( fileName !== ".DS_Store" && fileName !== "desktop.ini" && entry.type === "File") { 
                // 这里的判断是因为在解析完压缩文件后发现每个目录下都有个叫.DS_Store的奇怪东西
                // 查了才知道这是Mac系统的配置文件,这个当让不是我想上传的
                // desktop.ini是windows系统的配置文件
                    entry.on('data', function(chunck: any) {
                        let bs = new Stream.PassThrough() //很奇葩,云平台的接口对数据有要求,不得已又又做了一次流的转换
                        bs.end(chunck)
                        arr.push(
                            new Promise(function(resolve, reject) {
                                formUploader.putStream(token.uploadToken, `${prePath}${fileName}`, bs, putExtra, function(err, res, info) { //这是向云平台上传文件的方法
                                    if (err) {
                                        reject(err)
                                    }
                                    if (info.statusCode === 200) {
                                        resolve(res)
                                    } else {
                                        reject(res)
                                        reject(info.statusCode)
                                    }
                                })
                            })
                        )
                    })
                }
            })
          .once('close', function() {
                cb(arr) // 解压完成执行回调
            })
    }

unzip.Parse()方法是对压缩包进行递归解压,所以才能这么轻松的拿到解压后的所有文件,给它一个大大的赞~