首页 > 解决方案 > 上传块以使用 React 表达时,appendFileSync 未生成完整文件

问题描述

我正在尝试以快递方式实现块上传:

const cors = require('cors');
const express = require('express');
const md5 = require('md5');
const fs = require('fs');

const app = express()
const port = 4000

app.use(cors({origin: 'http://localhost:3000'}));
app.use(express.raw({type: 'application/octet-stream', limit: '100mb'}));

app.post('/upload', (req, res) => {
    const { name, currentChunkIndex, totalChunks } = req.query;
    const isFirstChunk = parseInt(currentChunkIndex) == 0;
    const isLastChunk
        = parseInt(currentChunkIndex) === parseInt(totalChunks) - 1;
    
    const ext = name.split('.').pop();
    const data = req.body.toString().split(',')[1];

    const buffer = Buffer.from(data);
    const tempFilename = 'tmp_' + md5(name + req.ip) + '.' + ext;

    if (isFirstChunk && fs.existsSync('./uploads/' + tempFilename)) {
        fs.unlinkSync('./uploads/' + tempFilename)
    }

    fs.appendFileSync('./uploads/' + tempFilename, buffer)

    if (isLastChunk) {
        const finalFileName = Date.now() + '.' + ext;
        fs.renameSync('./uploads/' + tempFilename, './uploads/' + finalFileName);
    }

    res.send('ok');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

我的反应调用使用以下工作人员:

import axios from 'axios';

const chunkSize = 1 * 1000000; //(10 MB)

const fileReader = blob => {
    return new Promise((resolve, _) => {
        const onloadHandler = e => {
            const data = e.target.result;
            resolve(data)
        };
    
        const reader = new FileReader();
        reader.onload = e => onloadHandler(e);
        reader.readAsDataURL(blob);
    });
};


const uploadWorker = file => {
    return new Promise(async(resolve, reject) => {
        const totalChunks = Math.ceil(file.size / chunkSize);
        console.log(`total chunks ${totalChunks}`);
        let currentChunkIndex = 0;
    
        while (currentChunkIndex < totalChunks) {
            console.log(`current chunk ${currentChunkIndex}`);
            const from = currentChunkIndex * chunkSize;
            const to = Math.min(from + chunkSize, file.size);
            const blob = file.slice(from, to);
            const data = await fileReader(blob);
    
            const params = new URLSearchParams();
            params.set('name', file.name);
            params.set('size', file.size);
            params.set('currentChunkIndex', currentChunkIndex);
            params.set('totalChunks', totalChunks);
    
            const headers = {'Content-Type': 'application/octet-stream'};
            const url = 'http://localhost:4000/upload?' + params.toString();

            await axios.post(url, data, { headers });
            currentChunkIndex += 1;
        }
        resolve();
    });
};

export default uploadWorker;

当我在 express 上调试时,我可以看到它正确接收每个块,并且确实将数据保存到uploads最终文件中,但它只是一个二进制文件,如果我尝试发送视频,我将无法观看视频。

与原始文件的 6.3mb 相比,保存的文件为 8.4mb...

有什么想法我在这里做错了吗?

标签: reactjsexpress

解决方案


推荐阅读