When we use Node to build a server, we may encounter the situation that we need to receive compressed files, such as receiving front-end submitted compressed packages, decompression, etc. Here we will demonstrate how to receive and decompress

The front end

html

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

<p id="desc">Click or drag the file to the web page to upload</p>
Copy the code

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.25 rem;
    color: #7c7c7c;
    transform: translate(-50%, -50%);
    z-index: -9999;
}
Copy the code

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)
	
    // Drag upload
    body.addEventListener('drop'.e= > {
        e.preventDefault()
        let fileList = e.dataTransfer.files
        beforeUpload(fileList)
    }, false)

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

	// Process the file to be uploaded
    function beforeUpload(fileList) {
        // Check whether it is a drag file operation to the page
        if (fileList.length === 0) {
            alert('Not selected file to upload')
            return
        }
        // Check whether the file is a ZIP package
        if (fileList[0].type.indexOf("application/zip") = = = -1) {
            alert('Only zip packages can be uploaded')
            return
        }
		
        let formData = new FormData()
        formData.append('file', fileList[0])

        request(formData)
    }

	// Send the request
    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('Upload successful')}else {
                alert('Upload failed,${response.message}`()}}}})Copy the code

The background

The background is set up using express. Run the following command to install the dependency:

yarn add express body-parser multer compressing
Copy the code

or

npm i express body-parser multer compressing -S
Copy the code

Our directory structure is as follows:

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

Entrance to the file

// 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('The server runs on http://127.0.0.1:8080')})Copy the code

Custom utility functions

// utils/index.js

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

// Write to the file
exports.writeFile = (filepath, data, encode) = > {
    return new Promise((resolve, reject) = > {
        fs.writeFile(filepath, data, encode, (err) = > {
            if (err) reject(err)
            resolve()
        })
    })
}


// Read the file
exports.readFile = (filepath, encode) = > {
    return new Promise((resolve, reject) = > {
        fs.readFile(filepath, encode, (err, data) = > {
            if (err) reject(err)
            resolve(data)
        })
    })
}


// Unzip the file
exports.extract = (filepath, outputPath) = > {
	// 
    return compressing.zip.uncompress(filepath, outputPath, {
        // Set Chinese decoding, important!!
        zipFileNameEncoding: 'utf8'})}// Delete files and folders
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)
    }
}
Copy the code

The routing file

// 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')
// The location where the compressed file is stored
const filePath = path.resolve(__dirname, '.. / '.'cache')

router.post('/api/upload', multer().single('file'), async (req, res) => {
    // Multer will automatically bind file data to req.file
    let file = req.file

    if(file.mimetype ! = ='application/zip') {
        res.send({ code: 400.state: false.message: 'Not a zip file'.data: 0})}try {
		// Delete the old directory
        delDir(filePath)
		// Rebuild the directory where the compressed file is stored
        fs.mkdirSync(filePath)
		// Get the file name of the compressed package
        let filename = path.join(filePath, file.originalname)
        // Save the compressed package file. File. buffer stores the binary data of the file
        await writeFile(filename, file.buffer, 'buffer')
        // Decompress the package
        await extract(filename, filePath)
        // Delete the compressed package after the decompression is complete
        fs.unlinkSync(filename)

        res.send({ code: 200.state: true.message: 'ok'})}catch (error) {
        console.log(error)
        res.send({ code: 400.state: false.message: 'Failed to extract zip file'.data: 0})}})module.exports = router
Copy the code

other

We decompressed using compressing, and be sure to set the Chinese decoding, otherwise Chinese garbled characters may appear

Of course, node-stream-zip and extract-zip, for example, also don’t parse Chinese, resulting in garbled characters