图片分片上传功能的实践

在 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 开发中常用的技术之一。

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

相关推荐
九九落21 分钟前
前端获取经纬度完全指南:从Geolocation API到地图集成
前端·获取经纬度
来恩100335 分钟前
jQuery选择器
前端·javascript·jquery
前端繁华如梦37 分钟前
树上挂苹果还是挂玻璃球?Three.js 程序化果实的完整实现指南
前端·javascript
墨痕诉清风44 分钟前
Web浏览器客户端检测网站网络健康(代码)
前端·网络·测试工具
IMPYLH1 小时前
Linux 的 wc 命令
linux·运维·服务器·前端·bash
happybasic1 小时前
Python库升级标准流程~
linux·前端·python
川冰ICE1 小时前
前端工程化深度实战:从Webpack5到Vite5的构建工具演进与选型决策
前端
Cosolar1 小时前
收藏备用!2026 年所有主流 RAG 开源项目都在这里了
人工智能·面试·llm
CDwenhuohuo1 小时前
优惠券组件直接用 uview plus
前端·javascript·vue.js
用户74090472362751 小时前
我用 curl 排查了一次 OpenAI-compatible API 连接失败:401、403、404 分别怎么定位
前端