0%

处理压缩文件

当我们在使用Node搭建服务端的时候,我们可能会碰到需要接收 压缩文件 的情况,例如:接收前端提交的压缩包、解压等,我们这里演示一下如何 接收解压

前端

html

<!-- pages/index.html -->

<p id="desc">点击或拖拽文件到网页内即可上传</p>

css

/* pages/index.html */

* {
margin: 0;
padding: 0;
list-style: none;
border: none;
box-sizing: border-box;
}

html,
body {
width: 100vw;
height: 100vh;
}

#desc {
position: fixed;
top: 50%;
left: 50%;
letter-spacing: 1em;
font-size: 1.25rem;
color: #7c7c7c;
transform: translate(-50%, -50%);
z-index: -9999;
}

js

// pages/index.html

(() => {

let body = document.body

body.addEventListener('dragenter', e => e.preventDefault(), false)

body.addEventListener('dragleave', e => e.preventDefault(), false)

body.addEventListener('dragover', e => e.preventDefault(), false)

// 拖拽上传
body.addEventListener('drop', e => {
e.preventDefault()
let fileList = e.dataTransfer.files
beforeUpload(fileList)
}, false)

// 点击上传
body.addEventListener('click', () => {
let fileInput = document.createElement('input')
fileInput.type = 'file'
fileInput.click()
fileInput.onchange = function () {
beforeUpload(this.files)
}
}, false)

// 处理要上传的文件
function beforeUpload(fileList) {
// 检测是否是拖拽文件到页面的操作
if (fileList.length === 0) {
alert('未选择要上传的文件')
return
}
// 检测文件是不是zip压缩包
if (fileList[0].type.indexOf("application/zip") === -1) {
alert('只能上传zip格式的压缩包')
return
}

let formData = new FormData()
formData.append('file', fileList[0])

request(formData)
}

// 发送请求
function request(formData) {
let xhr = new XMLHttpRequest()
xhr.open('POST', '/api/upload')
xhr.send(formData)
xhr.onload = function () {
let { response } = this
response = JSON.parse(response)
if (response.code === 200 && response.state === true) {
alert(`上传成功`)
} else {
alert(`上传失败,${response.message}`)
}
}
}

})()

后台

后台采用express搭建,执行以下命令进行依赖安装:

yarn add express body-parser multer compressing

npm i express body-parser multer compressing -S

我们的目录结构如下:

node_modules
cache
pages
- index.html
service
- index.js
utils
- index.js
main.js
package.json

入口文件

// main.js

const express = require('express')
const bodyParser = require('body-parser')
const router = require('./service/index')
const path = require('path')

const app = express()

app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

app.use(express.static(path.resolve(__dirname, 'pages')))

app.use(router)

app.listen(8080, () => {
console.log(`服务器运行于 http://127.0.0.1:8080`)
})

自定义工具函数

// utils/index.js

const fs = require('fs')
const compressing = require('compressing');

// 写入文件
exports.writeFile = (filepath, data, encode) => {
return new Promise((resolve, reject) => {
fs.writeFile(filepath, data, encode, (err) => {
if (err) reject(err)
resolve()
})
})
}


// 读取文件
exports.readFile = (filepath, encode) => {
return new Promise((resolve, reject) => {
fs.readFile(filepath, encode, (err, data) => {
if (err) reject(err)
resolve(data)
})
})
}


// 解压文件
exports.extract = (filepath, outputPath) => {
//
return compressing.zip.uncompress(filepath, outputPath, {
// 设置中文解码,重要!!!
zipFileNameEncoding: 'utf8'
})

}


// 删除文件和文件夹
exports.delDir = (filepath) => {

if (fs.existsSync(filepath)) {
const files = fs.readdirSync(filepath)
files.forEach((file) => {
const nextFilePath = `${filepath}/${file}`
const states = fs.statSync(nextFilePath)
if (states.isDirectory()) {
this.delDir(nextFilePath)
} else {
fs.unlinkSync(nextFilePath)
}
})
fs.rmdirSync(filepath)
}
}

路由文件

// router/index.js

const router = require('express').Router()
const fs = require('fs')
const multer = require('multer')
const path = require('path')
const { writeFile, extract, delDir } = require('../utils/index')
// 压缩文件存放的位置
const filePath = path.resolve(__dirname, '../', 'cache')

router.post('/api/upload', multer().single('file'), async (req, res) => {
// multer 会自动将文件数据绑定到req.file中
let file = req.file

if (file.mimetype !== 'application/zip') {
res.send({ code: 400, state: false, message: '不是zip文件', data: 0 })
}

try {
// 删除旧目录
delDir(filePath)
// 重建压缩文件存放的目录
fs.mkdirSync(filePath)
// 得到压缩包的文件名
let filename = path.join(filePath, file.originalname)
// 保存压缩包文件,file.buffer存放文件的二进制数据
await writeFile(filename, file.buffer, 'buffer')
// 解压压缩包
await extract(filename, filePath)
// 解压完成后,删除压缩包
fs.unlinkSync(filename)

res.send({ code: 200, state: true, message: 'ok' })
} catch (error) {
console.log(error)
res.send({ code: 400, state: false, message: 'zip文件解压失败', data: 0 })
}

})

module.exports = router

其他

我们解压使用的是 compressing 处理的,并且 一定要记得设置中文解码否则可能会出现中文乱码

当然,例如 node-stream-zipextract-zip 也无法解析中文,会出现乱码

-------------本文结束    感谢阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!