前端与MinIO协同:实现高效大文件分片上传

实现前端大文件分片上传至MinIO存储服务通常涉及以下步骤:

图片[1]_前端与MinIO协同:实现高效大文件分片上传_知途无界
  1. 前端代码:负责将大文件分割成小块(chunk),然后逐个上传到服务器。
  2. 后端代码:接收前端传来的文件块,并将它们按顺序存储到MinIO。
  3. 合并文件块:在所有块上传完成后,后端需要在MinIO中将这些块合并成一个完整的文件。

以下是一个简化的示例,展示了如何使用前端JavaScript(假设在浏览器环境中)和Node.js后端来实现这一功能。

前端代码(JavaScript)

// 假设我们有一个大文件file和MinIO服务器的上传URL  
async function uploadLargeFile(file, uploadUrl) {  
    const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB  
    const totalChunks = Math.ceil(file.size / CHUNK_SIZE);  
    let uploadedChunks = 0;  
  
    for (let start = 0; start < file.size; start += CHUNK_SIZE) {  
        const chunk = file.slice(start, start + CHUNK_SIZE);  
        const formData = new FormData();  
        formData.append('file', chunk);  
        formData.append('fileName', file.name);  
        formData.append('chunkIndex', uploadedChunks);  
        formData.append('totalChunks', totalChunks);  
  
        try {  
            await fetch(uploadUrl, {  
                method: 'POST',  
                body: formData,  
            });  
            uploadedChunks++;  
            console.log(`Uploaded chunk ${uploadedChunks}/${totalChunks}`);  
        } catch (error) {  
            console.error('Error uploading chunk:', error);  
            // 处理上传错误,可能需要重试机制  
        }  
    }  
  
    console.log('All chunks uploaded successfully!');  
}  
  
// 调用函数上传文件  
document.getElementById('uploadButton').addEventListener('click', async () => {  
    const fileInput = document.getElementById('fileInput');  
    const file = fileInput.files[0];  
    if (file) {  
        const uploadUrl = 'http://your-backend-server/upload'; // 替换为你的后端上传URL  
        await uploadLargeFile(file, uploadUrl);  
    }  
});

后端代码(Node.js + MinIO Client SDK)

const express = require('express');  
const multer = require('multer');  
const Minio = require('minio');  
const fs = require('fs');  
const path = require('path');  
  
const app = express();  
const upload = multer({ dest: 'uploads/' });  
  
const minioClient = new Minio.Client({  
    endPoint: 'localhost',  
    port: 9000,  
    useSSL: false,  
    accessKey: 'YOUR-ACCESSKEYID',  
    secretKey: 'YOUR-SECRETACCESSKEY',  
});  
  
app.post('/upload', upload.single('file'), async (req, res) => {  
    const { fileName, chunkIndex, totalChunks } = req.body;  
    const chunk = fs.readFileSync(req.file.path);  
  
    try {  
        // 存储每个块到MinIO,使用唯一的块名(例如:fileName.partX)  
        const chunkName = `${fileName}.part${chunkIndex}`;  
        await minioClient.putObject('my-bucket', chunkName, chunk);  
  
        // 如果这是最后一个块,则合并它们  
        if (parseInt(chunkIndex) === parseInt(totalChunks) - 1) {  
            await composeFile(fileName, totalChunks);  
        }  
  
        // 清理临时文件  
        fs.unlinkSync(req.file.path);  
  
        res.send('Chunk uploaded successfully');  
    } catch (err) {  
        console.error('Error uploading chunk to MinIO:', err);  
        res.status(500).send('Error uploading chunk');  
    }  
});  
  
// 合并文件块  
async function composeFile(fileName, totalChunks) {  
    const parts = [];  
    for (let i = 0; i < totalChunks; i++) {  
        parts.push({ ETag: await minioClient.getObjectETag('my-bucket', `${fileName}.part${i}`), PartNumber: i + 1 });  
    }  
  
    try {  
        await minioClient.composeObject('my-bucket', fileName, parts);  
  
        // 删除临时块  
        for (let i = 0; i < totalChunks; i++) {  
            await minioClient.removeObject('my-bucket', `${fileName}.part${i}`);  
        }  
  
        console.log('File composed successfully!');  
    } catch (err) {  
        console.error('Error composing file:', err);  
    }  
}  
  
app.listen(3000, () => {  
    console.log('Server is running on port 3000');  
});

注意

  1. 上述代码是一个简化的示例,没有包含完整的错误处理和重试机制。
  2. 在生产环境中,请确保对文件上传进行验证和安全性检查。
  3. minioClient的配置应根据你的MinIO服务器设置进行调整。
  4. 前端和后端代码需要部署到能够相互通信的环境中。
  5. multer用于处理前端传来的multipart/form-data,但你也可以选择其他中间件或方法来处理文件上传。
  6. 确保你的MinIO服务器配置正确,并且你的后端服务有权访问MinIO进行读写操作。
© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞86 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容