分片上传技术全解析:原理、优势与应用(含简单实现源码)

举报
watermelo37 发表于 2025/07/31 22:21:53 2025/07/31
【摘要】 作者:watermelo617涉及领域:Vue、SpingBoot、Docker、LLM、python--------------------------------------------------------------------------------------------------------------------------------------------------...


作者:watermelo617

涉及领域:Vue、SpingBoot、Docker、LLM、python

-------------------------------------------------------------------------------------------------------------------------

--------------------------温柔地对待温柔的人,包容的三观就是最大的温柔。--------------------------

-------------------------------------------------------------------------------------------------------------------------

分片上传技术全解析:原理、优势与应用(含简单实现源码)

一、什么是分片上传

        分片上传(Chunked Upload)是将大文件分成多个较小的部分(分片)来逐个上传到服务器。上传完成后,服务器将这些分片重新组装成原始文件。这个过程通常包括以下几个步骤:

  1. 分片:文件被切割成多个小的片段,每个片段的大小通常是预定义的。
  2. 上传:每个分片被单独上传到服务器。上传过程中,通常会附带分片的索引和其他元数据。
  3. 组装:服务器接收到所有分片后,将它们按正确的顺序重新组装成完整的文件。
  4. 确认:完成组装后,服务器可以返回一个确认响应,表示文件上传成功。

二、分片上传解决了什么问题

        分片上传是一个有效的处理大文件上传问题的方案,它通过将文件分割为小片段来提高上传的可靠性和效率,并确保数据的完整性。在网络环境环境不好,存在需要重传风险的场景,分片上传能有效提升上传的体验。

        其具体优势在于:

  1. 大文件上传的稳定性:对于大文件,直接上传可能会因为网络问题、超时等导致上传失败。分片上传可以在单个分片上传失败时仅重新上传失败的分片,而不是整个文件,提高了上传的成功率。
  2. 减少内存使用:分片上传可以将大文件拆分为较小的片段,这样可以减少内存消耗并优化上传性能。
  3. 断点续传:分片上传支持断点续传。即使上传过程中发生了中断,用户可以从中断的位置继续上传,不必从头开始。
  4. 负载均衡:可以在多个服务器之间分配分片上传任务,提高系统的负载均衡能力。

三、分片上传的本质

3.1、分片上传的本质意义

        分片上传的本质就是将大文件分割成多个较小的部分,逐个上传到服务器,然后在服务器端将这些部分重新组合成完整的文件。这种方法不仅解决了大文件上传的问题,还能优化网络带宽和提高上传效率。

        大多数情况下,服务器会负责将接收到的分片重新组装成完整的文件。服务器通常会根据分片的索引顺序将它们拼接起来。在某些情况下,客户端可能会将所有分片上传到服务器后,由客户端自行处理合并操作(通常较少见)。

3.2、分片上传的风险与规避方式

①网络问题

        网络中断可能导致某些分片上传失败。为了应对这种情况,可以实现重试机制和断点续传功能。

②服务器端错误

        服务器在接收和组装分片时可能会发生错误。应确保服务器有适当的错误处理和日志记录机制。

③文件完整性校验

        为了确保文件在上传和组装过程中没有发生损坏,通常会计算文件的哈希值,并在上传完成后进行校验。在第四部分案例代码中使用了SparkMD5来计算文件的MD5哈希值,以确保文件的一致性和完整性。

3.3、分片上传中的重试机制与断点续传

        这些技术可以结合使用,以提高上传的鲁棒性。重试机制确保分片上传的稳定性,断点续传支持上传中断后的恢复。

①重试机制

        重试机制是在上传过程中,如果遇到网络问题、服务器错误或其他上传失败的情况,自动重新尝试上传失败的部分(通常是分片上传中会使用重试机制)。适用于网络不稳定或服务器偶尔出现故障的情况。可以做到:

  • 提高成功率:自动处理上传失败的情况,提高上传成功率。
  • 错误恢复:在上传过程中遇到错误时,可以自动恢复,无需用户干预。
  • 可配置性:重试次数和时间间隔可以进行配置,以适应不同的需求和网络环境。

②断点续传

        断点续传断点续传是允许在上传过程中中断后,能够从中断的位置继续上传,而不是从头开始。这通常涉及记录已上传的部分,并在恢复时跳过这些已上传部分。

        一般来说,断点续传是从断开的分片起,重新上传该分片及之后的分片。但也有更精细的实现方式,从精确的分片的断点位置起,这样在中断频繁的网络环境中表现更好,可以避免重复上传已经部分成功的内容。更加高效和灵活,但实现复杂度较高。

        断点续传有助于:

  • 中断恢复:在上传过程中,如果发生中断,可以从中断点继续上传,而不是重新上传整个文件。
  • 记录状态:需要在客户端或服务器端记录上传进度。
  • 用户体验:提升用户体验,避免长时间上传过程中的中断带来的困扰。

四、基于js的简单实现案例

        前端代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <input id="upload" type="file" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.2/spark-md5.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.7.2/axios.min.js"></script>
    <script>
        // 如何获取input,监听上传事件
        var inputs = document.getElementById('upload')
        inputs.onchange = async () => {
            // console.log(inputs.files, 'file')
            // 获取到上传的文件对象
            var file = inputs.files[0]
            // 创建分片数据
            var chunks = createChunk(file, 50 * 1024 *1024)
           
            // 文件内容创建hash
            var res = await hash(chunks)
            console.log(res, 'hash')
            // 调用发送分片的接口
            uploadChunk(chunks, res, file.name)
        }

        // 创建分片
        function createChunk(file, chunkSize) {
            const result = []
            for (let i = 0; i < file.size; i += chunkSize) {
                result.push(file.slice(i, i + chunkSize))
            }
            return result
        }

        // 根据文件内容创建hash值
        function hash(chunks) {
            return new Promise((resolve) => {
                var spark = new SparkMD5()
                // 递归
                function _read(i) {
                    if (i >= chunks.length) {
                        resolve(spark.end())
                        return
                    }
                    // 获取当前其中的一个片段
                    var blob = chunks[i]
                    // 创建一个FileReader对象
                    var reader = new FileReader()
                    reader.onload = e => {
                    var bytes = e.target.result
                    spark.append(bytes)
                    _read(i + 1)
                    }

                    reader.readAsArrayBuffer(blob)
                }
                _read(0)
            })
        }

        // 分片上传
        function uploadChunk(chunks, hash, fileName) {
            // 文件怎么样传给后端? ok
            // 所有分片上传成功后,有一个通知告诉后端已经上传完成?
            var taskArr = []
            chunks.forEach((chunk, index) => {
                var formdata = new FormData()
                formdata.append('chunk', chunk)
                formdata.append('chunkName', `${hash}-${index}-${fileName}`)
                formdata.append('fileName', fileName)
                var task = axios.post('http://127.0.0.1:3000/upload', formdata, {
                    headers: {
                        'Content-Type': 'multipart/form-data'
                    }
                })
                taskArr.push(task)
            });
            Promise.all(taskArr).then(() => {
                // 所有分片上传成功后的结果
                console.log('通知后端')
            })
            
        }
    </script>
</body>

</html>

         极简的后端接口(模拟发送请求,不具备实际后端作用):

const express = require('express')
const cors = require('cors')
const app = express()

app.use(cors())

const hostname = '127.0.0.1'
const port = 3000

app.use(express.json())

// 模拟支付
app.post('/upload', (req, res) => {
  res.status(200).json({})
})

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

五、总结

        分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。

         博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        更多优质内容,请关注

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。