图片分片上传功能的实践

在 Web 开发中,图片上传是一个常见的需求,特别是对于大文件,为了提高上传效率和稳定性,常常需要将文件进行分片上传。本文将介绍如何利用 JavaScript 和 Axios 库实现图片分片上传功能。

HTML部分

首先,我们在 HTML 中创建一个文件上传的 input 元素,以及显示上传进度的 progress 元素和开始上传按钮。

html 复制代码
<body>
    // 上传组件
    <input type="file" id="upload"/> 
    // 进度条
    <progress id="progress" value="0" max="100"></progress> 
    // 上传按钮
    <button id="start">开始上传</button>
</body>

JavaScript部分

然后,我们使用 JavaScript 编写上传功能。以下是 JavaScript 代码:

javascript 复制代码
import axios from "axios";
// 上传组件
const upload = document.querySelector('#upload');
// 进度条
const progress = document.querySelector('#progress');
// 上传按钮
const start = document.querySelector('#start');

// 上传的服务器地址
const uploadApiPath = `http://localhost:8888/upload`;

// 点击开始上传按钮触发事件
start.addEventListener('click', () => {
  // 获取文件
  const [file] = upload.files;

  if (!file) {
    throw new Error('请选择文件');
  }
  
  // 分片大小,2MB
  const chunkSize = 1024 * 1024 * 2; 

  // 创建文件切片
  const createFileChunk = (file, size = chunkSize) => {
    const fileChunkList = [];
    let cur = 0;
    while (cur < file.size) {
      const chunk = file.slice(cur, cur + size);
      fileChunkList.push(chunk);
      cur += size;
    }

    return fileChunkList;
  };

  const chunks = createFileChunk(file);

  // 上传文件切片
  const uploadChunks = async (chunks) => {
    const requestList = chunks.map((chunk, index) => {
      const formData = new FormData();
      formData.append('file', chunk);
      formData.append('filename', file.name);
      formData.append('index', index);
      return { formData };
    });
    
    // 分片上传列表
    const requestListLength = requestList.length;
    // 已上传完成数
    let completed = 0;

    // 递归上传文件切片
    const upload = async () => {
      if (completed >= requestListLength) {
        // 上传完成
        console.log('上传完成');
        return;
      }
      const request = requestList[completed];
      
      try {
        // 发送 POST 请求上传文件切片
        const res = await axios.post(uploadApiPath, request.formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        });
        // 更新上传进度
        progress.value = Math.floor((completed + 1) / requestListLength * 100);
        completed++;
        await upload();
      } catch (error) {
        console.log(error);
      }
    };

    await upload();
  };

  uploadChunks(chunks).then(r => {});

});

服务端部分

以下是服务端部分的代码,基于Express框架实现了文件上传的接口:

javascript 复制代码
import express from 'express';
import bodyParser from 'body-parser';
import fileUpload from 'express-fileupload';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
import { existsSync, unlinkSync, writeFileSync, appendFileSync } from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const app = express();

// 开启跨域
app.all('*', (req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
})

// 处理urlencoded请求
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// 使用express-fileupload中间件处理文件上传
app.use(fileUpload({}));

// 处理静态文件
app.use('/', express.static('static'));

const port = 8888;

app.get('/', (req, res) => {
    res.send({
      code: 200,
      message: 'Hello World!'
    });
})

app.post('/upload', (req, res) => {
  const { file } = req.files;
  const { filename, index } = req.body;

  console.log(file, filename, index)

  const filePath = resolve(__dirname, `./static/${filename}`);

  const url = `http://localhost:${port}/${filename}`

  if (parseInt(index) === 0) {
    if (existsSync(filePath)) {
      // 文件已存在,删除
      unlinkSync(filePath);
    }
    // 写入一个新文件
    writeFileSync(filePath, file.data);

    res.send({
      code: 200,
      message: '创建文件成功',
      url
    });
  } else {
    // 追加文件
    appendFileSync(filePath, file.data);
    res.send({
      code: 200,
      message: '追加文件成功',
      url
    });
  }
})

app.listen(port, () => {
  console.log(`Server is running on port http://localhost:${port}`);
})

通过本文的介绍,我们学习了如何使用 JavaScript 和 Axios 库实现图片分片上传功能,同时也了解了服务端部分的实现细节。这种方式可以提高大文件上传的效率和稳定性,是 Web 开发中常用的技术之一。

希望本文对您有所帮助,谢谢阅读!

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅7 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端