当前位置:首页 > VUE

vue实现切片上传

2026-02-19 05:21:39VUE

切片上传实现原理

切片上传的核心是将大文件分割为多个小块(chunk),分批上传到服务器。服务器接收后合并这些切片,最终还原完整文件。这种方式能有效解决大文件上传超时、网络不稳定等问题,并支持断点续传。

前端实现步骤

HTML部分 创建文件选择控件和上传按钮,监听文件选择事件:

<input type="file" @change="handleFileChange" />
<button @click="handleUpload">上传</button>

定义切片方法 通过Blob.prototype.slice方法实现文件分片:

function createChunks(file, chunkSize) {
  const chunks = []
  let start = 0
  while (start < file.size) {
    chunks.push({
      chunk: file.slice(start, start + chunkSize),
      filename: file.name
    })
    start += chunkSize
  }
  return chunks
}

上传逻辑实现 使用FormData携带切片数据,注意添加切片序号和文件hash标识:

async function uploadChunks(chunks) {
  const requests = chunks.map((chunk, index) => {
    const formData = new FormData()
    formData.append('chunk', chunk.chunk)
    formData.append('filename', chunk.filename)
    formData.append('hash', `${fileHash}-${index}`)
    return axios.post('/upload', formData)
  })
  await Promise.all(requests)
}

后端处理要点

接收切片 使用multer等中间件处理文件上传:

app.post('/upload', upload.single('chunk'), (req, res) => {
  const { filename, hash } = req.body
  fs.renameSync(req.file.path, `temp/${hash}`)
  res.send({ status: 'success' })
})

合并切片 当所有切片上传完成后触发合并操作:

function mergeFiles(filename, chunkCount) {
  const writeStream = fs.createWriteStream(`uploads/${filename}`)
  for (let i = 0; i < chunkCount; i++) {
    const chunkPath = `temp/${fileHash}-${i}`
    writeStream.write(fs.readFileSync(chunkPath))
    fs.unlinkSync(chunkPath)
  }
  writeStream.end()
}

优化功能实现

文件哈希生成 使用spark-md5计算文件唯一标识:

function calculateHash(file) {
  return new Promise(resolve => {
    const spark = new SparkMD5.ArrayBuffer()
    const reader = new FileReader()
    reader.onload = e => {
      spark.append(e.target.result)
      resolve(spark.end())
    }
    reader.readAsArrayBuffer(file)
  })
}

断点续传支持 上传前检查服务器已存在的切片:

async function checkExistingChunks(fileHash, chunkCount) {
  const { data } = await axios.get('/check', {
    params: { fileHash, chunkCount }
  })
  return data.existedChunks
}

进度显示 利用axios的onUploadProgress回调更新进度:

vue实现切片上传

axios.post('/upload', formData, {
  onUploadProgress: progressEvent => {
    const percent = Math.round(
      (progressEvent.loaded / progressEvent.total) * 100
    )
    console.log(`当前切片上传进度:${percent}%`)
  }
})

完整示例组件

<template>
  <div>
    <input type="file" @change="handleFileChange" />
    <button @click="handleUpload">上传</button>
    <div>进度:{{ progress }}%</div>
  </div>
</template>

<script>
import axios from 'axios'
import SparkMD5 from 'spark-md5'

export default {
  data() {
    return {
      file: null,
      progress: 0
    }
  },
  methods: {
    handleFileChange(e) {
      this.file = e.target.files[0]
    },
    async handleUpload() {
      if (!this.file) return

      const fileHash = await this.calculateHash(this.file)
      const chunks = this.createChunks(this.file, 1024 * 1024) // 1MB每片

      const existedChunks = await this.checkExistingChunks(fileHash, chunks.length)
      const requests = chunks
        .filter((_, index) => !existedChunks.includes(index))
        .map((chunk, index) => this.uploadChunk(chunk, fileHash, index))

      await Promise.all(requests)
      await this.mergeFiles(fileHash, this.file.name)
    },
    // 其他方法实现参考前述代码片段
  }
}
</script>

标签: 切片上传
分享给朋友:

相关文章

Vue实现头像截取上传

Vue实现头像截取上传

Vue实现头像截取上传的方法 使用Vue实现头像截取上传功能,可以通过以下步骤完成。主要依赖第三方库vue-cropper或cropperjs实现图像裁剪功能,结合文件上传逻辑完成整个流程。 安装依…

如何实现react时间切片

如何实现react时间切片

React 时间切片实现方法 React 时间切片(Time Slicing)是通过将渲染任务分解为小块并在浏览器空闲时执行,以避免长时间任务阻塞主线程。以下是实现方法: 使用 React 的 Co…

react实现上传

react实现上传

React 实现文件上传 在 React 中实现文件上传功能通常涉及以下几个关键步骤: 创建文件输入组件 使用 <input type="file"> 元素创建文件选择器,通过 onCh…

php实现上传视频文件

php实现上传视频文件

上传视频文件的基本实现 在PHP中实现视频文件上传需要处理文件接收、验证、移动和存储等步骤。以下是一个完整的实现示例: <?php if ($_SERVER['REQUEST_METHOD']…

php实现上传实例

php实现上传实例

PHP 文件上传实现 在 PHP 中实现文件上传功能需要结合 HTML 表单和 PHP 文件处理逻辑。以下是一个完整的实现示例: HTML 表单部分 创建一个包含文件上传字段的表单,确保设置 enc…

php 实现视频上传

php 实现视频上传

视频上传的基本实现 在PHP中实现视频上传需要处理文件上传、验证和存储。以下是一个基本的实现方法: 创建HTML表单,设置enctype为multipart/form-data: <form…