使用express JS和react JS上传文件

问题描述 投票:0回答:1

我想将单个文件从 React 前端上传到 Express 服务器。文件将在本地(在前端)被分成多个块,然后这些块将并行上传到服务器(一次最多 6 个请求),上传应该是可恢复的,这意味着如果在上传过程中连接丢失,然后在下次尝试时我们不必再次上传整个文件,它应该只上传剩余的部分/块。

当服务器接收到所有块时,它们应该以正确的顺序连接,以便我们可以取回原始文件,就像上传之前在客户端一样。请让我知道如何完成,我是在全栈应用程序中上传文件的新手。

reactjs node.js express file-upload chunks
1个回答
0
投票

首先你需要处理前端的分块

function fileChunker(file, chunkSize = 1024 * 1024) { // default chunk size of 1MB
    let chunks = [];
    let count = Math.ceil(file.size / chunkSize);
    
    for (let i = 0; i < count; i++) {
        let start = i * chunkSize;
        let end = start + chunkSize;
        chunks.push(file.slice(start, end));
    }
    
    return chunks;
}

然后你就得在前端处理上传了

async function uploadChunks(chunks, fileId) {
    const uploadChunk = async (chunk, index) => {
        const formData = new FormData();
        formData.append("file", chunk);
        formData.append("index", index);
        formData.append("fileId", fileId);

        return fetch("/upload", { method: "POST", body: formData });
    };

    let promises = [];
    for (let i = 0; i < chunks.length; i++) {
        promises.push(uploadChunk(chunks[i], i));
        if (promises.length === 6 || i === chunks.length - 1) {
            await Promise.all(promises);
            promises = [];
        }
    }
}

然后在后端,您必须处理将块保存到磁盘以进行合并

const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');

const app = express();
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
    const { index, fileId } = req.body;
    const filePath = path.join('uploads', `${fileId}-${index}`);

    // Save the chunk to disk with a unique name
    fs.rename(req.file.path, filePath, (err) => {
        if (err) return res.status(500).send('Error saving chunk.');
        res.send('Chunk uploaded successfully.');
    });
});

然后合并

function mergeChunks(fileId, totalChunks) {
    const fileStream = fs.createWriteStream(`uploads/${fileId}`);

    for (let i = 0; i < totalChunks; i++) {
        let chunkPath = path.join('uploads', `${fileId}-${i}`);
        let chunk = fs.readFileSync(chunkPath);
        fileStream.write(chunk);
        fs.unlinkSync(chunkPath); // optionally delete the chunk file after merging
    }

    fileStream.end();
}

© www.soinside.com 2019 - 2024. All rights reserved.