HTML5怎样实现文件分片加密上传

来源:中国站长站作者:小鱼头衔:草根站长
导读:本期聚焦于小伙伴创作的《HTML5怎样实现文件分片加密上传》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《HTML5怎样实现文件分片加密上传》有用,将其分享出去将是对创作者最好的鼓励。

HTML5提供了File API、Blob对象等能力,让前端可以直接操作本地文件,结合加密算法和分片上传逻辑,就能实现安全的大文件上传功能。整个流程分为前端分片切割、分片加密、分片上传、后端合并几个核心环节,下面逐步讲解实现方式。

HTML5怎样实现文件分片加密上传

核心实现思路

整体流程如下:首先通过<input type="file">获取用户选择的文件,使用Blob的slice方法将文件切割为固定大小的分片,对每个分片使用加密算法处理后再上传到服务端,服务端接收所有分片后按顺序合并为完整文件,同时校验文件完整性。

前端核心实现步骤

1. 文件选择与分片切割

首先通过File API获取文件对象,定义分片大小,循环切割文件得到所有分片:

// 获取文件对象
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
// 定义分片大小 2MB
const chunkSize = 2 * 1024 * 1024;
const chunkCount = Math.ceil(file.size / chunkSize);
const chunks = [];

for (let i = 0; i < chunkCount; i++) {
  const start = i * chunkSize;
  const end = Math.min(start + chunkSize, file.size);
  // 切割分片
  const chunk = file.slice(start, end);
  chunks.push({
    index: i,
    chunk: chunk,
    total: chunkCount,
    fileName: file.name,
    fileSize: file.size
  });
}

2. 分片加密处理

这里使用常见的AES加密算法对分片内容加密,需要先引入加密库,也可以自行实现基础加密逻辑,以下示例使用CryptoJS进行AES加密:

// 引入CryptoJS后使用
const encryptKey = 'your_encrypt_key_16'; // 16位加密密钥
function encryptChunk(chunk) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsArrayBuffer(chunk);
    reader.onload = function(e) {
      const wordArray = CryptoJS.lib.WordArray.create(e.target.result);
      // AES加密
      const encrypted = CryptoJS.AES.encrypt(wordArray, CryptoJS.enc.Utf8.parse(encryptKey), {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
      });
      resolve(encrypted.toString());
    };
  });
}

3. 分片上传实现

遍历所有分片,先加密再上传,同时可以添加断点续传逻辑,通过记录已上传的分片索引避免重复上传:

const uploadedChunks = new Set(); // 记录已上传分片索引
async function uploadChunks() {
  for (let item of chunks) {
    if (uploadedChunks.has(item.index)) continue;
    const encryptedData = await encryptChunk(item.chunk);
    const formData = new FormData();
    formData.append('chunk', encryptedData);
    formData.append('index', item.index);
    formData.append('total', item.total);
    formData.append('fileName', item.fileName);
    formData.append('fileSize', item.fileSize);
    // 上传分片
    await fetch('https://ipipp.com/upload_chunk', {
      method: 'POST',
      body: formData
    });
    uploadedChunks.add(item.index);
  }
  // 所有分片上传完成后通知服务端合并
  await fetch('https://ipipp.com/merge_chunks', {
    method: 'POST',
    body: JSON.stringify({
      fileName: file.name,
      total: chunkCount,
      fileSize: file.size
    }),
    headers: {
      'Content-Type': 'application/json'
    }
  });
}

后端实现要点

1. 分片接收存储

服务端接收分片后,将加密的分片临时存储,按文件名和分片索引命名,方便后续合并:

import os
from flask import Flask, request, jsonify

app = Flask(__name__)
UPLOAD_DIR = './upload_chunks'

@app.route('/upload_chunk', methods=['POST'])
def upload_chunk():
    chunk = request.files.get('chunk')
    index = request.form.get('index')
    file_name = request.form.get('fileName')
    # 创建临时存储目录
    file_dir = os.path.join(UPLOAD_DIR, file_name)
    if not os.path.exists(file_dir):
        os.makedirs(file_dir)
    # 保存分片 命名为 索引_分片内容
    chunk.save(os.path.join(file_dir, f'{index}.chunk'))
    return jsonify({'code': 0, 'msg': '上传成功'})

2. 分片合并与解密

接收合并请求后,按索引顺序读取所有分片,先解密再合并为完整文件:

import CryptoJS
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import json

@app.route('/merge_chunks', methods=['POST'])
def merge_chunks():
    data = json.loads(request.data)
    file_name = data.get('fileName')
    total = data.get('total')
    file_dir = os.path.join(UPLOAD_DIR, file_name)
    # 按索引顺序读取分片
    chunks = []
    for i in range(total):
        chunk_path = os.path.join(file_dir, f'{i}.chunk')
        with open(chunk_path, 'rb') as f:
            encrypted_data = f.read()
            # AES解密
            cipher = AES.new(b'your_encrypt_key_16', AES.MODE_ECB)
            decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size)
            chunks.append(decrypted_data)
    # 合并为完整文件
    final_path = os.path.join('./upload_files', file_name)
    with open(final_path, 'wb') as f:
        for chunk in chunks:
            f.write(chunk)
    # 删除临时分片
    for i in range(total):
        os.remove(os.path.join(file_dir, f'{i}.chunk'))
    os.rmdir(file_dir)
    return jsonify({'code': 0, 'msg': '文件合并完成'})

注意事项

  • 加密密钥需要妥善保管,避免前端硬编码密钥导致泄露,生产环境建议使用服务端下发临时密钥的方式。
  • 分片大小可以根据网络情况调整,一般建议1-5MB之间,过小会增加请求次数,过大容易上传失败。
  • 可以添加文件哈希校验,比如使用SparkMD5计算文件整体哈希,上传完成后校验哈希值确保文件完整。
  • 断点续传需要服务端提供查询已上传分片的接口,前端初始化时先查询已上传的分片索引,跳过已上传的部分。

HTML5分片上传文件加密File_APISparkMD5修改时间:2026-07-23 06:48:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。