惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
博客园 - 聂微东
Application and Cybersecurity Blog
Application and Cybersecurity Blog
MyScale Blog
MyScale Blog
罗磊的独立博客
H
Help Net Security
L
LangChain Blog
T
Threat Research - Cisco Blogs
量子位
S
Securelist
Last Week in AI
Last Week in AI
L
Lohrmann on Cybersecurity
T
The Exploit Database - CXSecurity.com
P
Privacy International News Feed
The Hacker News
The Hacker News
Vercel News
Vercel News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Blog of Author Tim Ferriss
T
Threatpost
Security Latest
Security Latest
P
Palo Alto Networks Blog
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
F
Full Disclosure
WordPress大学
WordPress大学
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Heimdal Security Blog
J
Java Code Geeks
Recorded Future
Recorded Future
Hugging Face - Blog
Hugging Face - Blog
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
阮一峰的网络日志
阮一峰的网络日志
U
Unit 42
B
Blog RSS Feed
月光博客
月光博客
C
Cisco Blogs
V
Visual Studio Blog
D
DataBreaches.Net
H
Hacker News: Front Page
博客园 - 叶小钗
N
News and Events Feed by Topic
爱范儿
爱范儿
A
Arctic Wolf

大佬论坛

52161.com 六一特价 500 易名 天涯这波是小作坊捞钱的吗,感觉很不专业的样子,居然连cdn都不用! 新天涯社区,卡爆了进不去啊! 20万拍到的域名,现在能涨到200万了吧 慢讯 关于天涯社区恢复访问进展的情况说明 新米 Gooey.cn 单词域名 1万左右收单字符域名,最好带V或者S,后缀最多不超过2位数 who.cx 现在已经不如 hu.is 好用了,这是怎么了? 最后几个四字母了,1588一个任选~ AI 做的图床真好看 用Discourse做论坛快到半个月了 兄弟们,我刚注册了域名 yin.hu 阴户 怎么样? 腾讯周年是啥时候 岛链壁纸主题开源 观星步入测试阶段 618和双十一哪个更火爆 nodebb.cc flarum.cc 出两个CC 天涯论坛明天回归了我感觉有压力 真正的天涯即将回归 你一定会用到的网站-WOCAONI.MA 上线 终于想到域名能做什么项目了。不容易啊。 沐雨云襄阳云服务器,性价比拉满 新米cdpc.cc niubi.ren 收一千五以内的单字符有木有 全国入户调查明天开始。。。 快快快!!Colocrossing洛杉矶补货补货了特供3c4g款20刀/年小鸡! 【开源自荐】耗费了几百亿token,我写了一个可以在浏览器运行的仿安卓系统 组合米,米表+交易站,打包888 5月满签记录记录!!! 小米御7 miyu7.com 只需288 2931.vip 29年到期,400出,全网最低价 香港 4-4 年付145 nmbai.cn 阿里的cn续费涨价了 cn也涨价了 ilaien.com 2017年注册 27年9月到期 68出 终于学会用frp啦,这下再也没有空间焦虑啦 安卓 除了 跳过广告的软件 大家还装了什么APP 下月见 昨晚在阿里云买了两个米 出 sss.hk 8元出一个国别单拼 AI智音 属于自己网站的音乐播放器!~ Nginx目前存在远程执行高危漏洞 浪费半天时间完活儿 周末这个签到活跃度,魔域论坛实锤了 写了个wordpress壁纸主题 趣域我老是输成QUYU.NET 大佬论坛还是太权威了 还缺啥 拿下了冷泡茶,做个调查 ai不是起中文名吗,坑我好几百 四个高频单词.yun打包200,易名p 刚刚获得一个新域名 caonimabi.de 观星,来咯,进度推进中 miqingju.com 加入了广告了😔 三个终端域名出,只卖一天 uiliuili.com U站,UI设计,188甩 一个多月来才收到一次打赏 mibiao.vip米表展示 15元出一个zblog的个人博客主题 Proxy001——500MB免费测试!高纯净度住宅代理IP!按GB计费!💥 是不是大家需要站点统计呢 大家最不能动摇的择偶标准是什么? 新写了个简单干净的米表:023.me 大佬们都是怎么统计自己网站的数据的 听说微信支持 PayPal 扫码支付了。 域名清仓…… .si 域名被炒起来了 捡漏越来越难了 原来世界上,还有这么好用的开源项目 山海间主题,多集功能 NaiYuan.com 易名3000 看上改价 第一次出米,虽然是亏本价。 mibiao.vip出出米表 查最低注册价格的网站是多少来着 记录一下剁手环节 欢迎佬们提交 准备开通这个邮箱,玩儿 推荐帖-推荐一个在线客服工具 终于,这个米是我的了 自己注册的公司没有实际经营,只有公众号和支付宝还有必要保留吗 互联功能 如果新建一个博客你会选Halo还是Wordpress 2026世界杯业务怎么部署服务器?美国香港双节点这样搭最省心 又入手了一个3字母cc 收个闲置的子比账号 有个COM域名,看有没有人想注册的 Sedo要被出售了 ,不知道会不会被狗爹接盘 gemini上不去了吗? 出几个玉米 从0到1写个仿微信朋友圈 认证了~ chedidi.cn 发现一个有趣的个人页 自己研究的wordpress主题更新,并正式上线,大佬们来捧捧场! 赛博朋克风音乐源码 继续低价出v p n好米 [开源] Stalux - 基于 Astro 的现代化静态博客主题,开箱即用 yaniu.net 是哪位大神的导航站
[PHP] 文件二进制分片切割加密传输 - 大佬论坛
希米 · 2026-06-20 · via 大佬论坛

说明:

1.  前端将文件分片加密后上传,后端存储加密数据和索引

2. 下载时前端获取索引,逐片下载解密并合并成原文件

3. 加密方式是 AES-256 ,调用Crypto库前端执行的;

4.就一个演示案例,没有写后台,就两个文件,前端html,后端php;

5.文件上传在“uploads”目录内,可以打开php文件自己修改;

6.主要用途就是减少网络波动导致文件传输不稳定,与服务器上传文件大小限制;

7.传输实时显示进度条,使用的是4线程并发传输,局域网测试可以跑满带宽;

代码:

index.html

<!-- 
   Title:文件二进制分片加密传输
    Blog:https://www.ximi.me
    Author:希米
    Time:2036-06-19
    说明:
      - 前端将文件分片加密后上传,后端存储加密数据和索引
      - 下载时前端获取索引,逐片下载解密并合并成原文件
-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>文件二进制分片加密传输</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js"></script>
</head>

<body class="bg-gray-100 p-6">

<div class="max-w-2xl mx-auto space-y-6">

<h1 class="text-2xl font-bold text-center"> 文件二进制分片加密传输演示</h1>

<!-- 密钥 -->
<div class="bg-white p-4 rounded-xl">
  <input id="key" type="password" placeholder="加密密钥"
    class="w-full p-3 border rounded">
</div>

<!-- 上传 -->
<div class="bg-white p-4 rounded-xl">
  <h2 class="font-bold mb-2">上传文件</h2>

  <input type="file" id="file" class="mb-3">

  <button onclick="upload()" class="bg-blue-500 text-white px-4 py-2 rounded">
    开始上传
  </button>

  <div id="upStatus" class="text-sm mt-2 text-gray-600"></div>
  <progress id="upProgress" value="0" max="100" class="w-full mt-2"></progress>
</div>

<!-- 下载 -->
<div class="bg-white p-4 rounded-xl">
  <h2 class="font-bold mb-2">下载文件</h2>

  <input id="fid" placeholder="文件ID" class="w-full p-2 border mb-3">

  <button onclick="downloadFile()" class="bg-purple-500 text-white px-4 py-2 rounded">
    开始下载
  </button>

  <div id="downStatus" class="text-sm mt-2 text-gray-600"></div>
  <progress id="downProgress" value="0" max="100" class="w-full mt-2"></progress>
</div>

</div>

<script>


// ================= 工具 =================
function sha256(str){
  return CryptoJS.SHA256(str).toString();
}

function safeJSON(t){
  try{
    return JSON.parse(t);
  }catch(e){
    console.log("❌ 后端返回:", t);
    throw new Error("JSON解析失败");
  }
}

// ================= 并发池 =================
async function asyncPool(limit, arr, fn){
  const ret = []
  const executing = []

  for(const item of arr){
    const p = Promise.resolve().then(()=>fn(item))
    ret.push(p)

    const e = p.then(()=>executing.splice(executing.indexOf(e),1))
    executing.push(e)

    if(executing.length >= limit){
      await Promise.race(executing)
    }
  }

  return Promise.all(ret)
}

// ================= 上传(并行版) =================
async function upload(){

  const file = document.getElementById('file').files[0]
  const key = document.getElementById('key').value

  if(!file || !key) return alert("缺文件或密钥")

  const status = document.getElementById('upStatus')
  const bar = document.getElementById('upProgress')

  const buf = await file.arrayBuffer()
  const chunkSize = 256 * 1024

  const chunks = []
  const originalName = file.name

  // ================= 切块 =================
  for(let i=0;i<buf.byteLength;i+=chunkSize){

    const slice = buf.slice(i, i+chunkSize)

    const word = CryptoJS.lib.WordArray.create(slice)

    const encrypted = CryptoJS.AES.encrypt(word, key).toString()

    const name = Math.random().toString(36).slice(2) + ".bin"

    chunks.push({
      index: i,
      name,
      data: encrypted,
      hash: sha256(encrypted)
    })
  }

  const fileId = "f_" + Date.now()

  let done = 0
  const start = Date.now()

  status.innerText = "并行上传中..."

  // ================= 并行上传(核心) =================
  await asyncPool(4, chunks, async (c)=>{

    const fd = new FormData()
    fd.append("id", fileId)
    fd.append("name", c.name)
    fd.append("chunk", c.data)

    const res = await fetch("file.php?action=upload",{
      method:"POST",
      body:fd
    })

    const text = await res.text()
    const data = safeJSON(text)

    if(data.status !== "ok"){
      throw new Error("upload fail")
    }

    done++
    bar.value = (done / chunks.length) * 100

    let speed = (done / ((Date.now()-start)/1000)).toFixed(2)

    status.innerText = `上传 ${done}/${chunks.length} 速度:${speed}/s`
  })

  // ================= manifest =================
  const manifest = {
    originalName,
    chunks: chunks.map(c=>({
      name:c.name,
      hash:c.hash
    }))
  }

  const fd2 = new FormData()
  fd2.append("id", fileId)
  fd2.append("manifest", JSON.stringify(manifest))

  await fetch("file.php?action=upload",{
    method:"POST",
    body:fd2
  })

  bar.value = 100
  status.innerText = "上传完成 ID: " + fileId
}

// ================= 下载(并行版) =================
async function downloadFile(){

  const id = document.getElementById('fid').value
  const key = document.getElementById('key').value

  const status = document.getElementById('downStatus')
  const bar = document.getElementById('downProgress')

  const res = await fetch("file.php?action=send&id="+id)
  const text = await res.text()

  const data = safeJSON(text)

  if(data.status !== "ok"){
    throw new Error(data.msg)
  }

  const manifest = data.manifest
  const list = manifest.chunks
  const originalName = manifest.originalName

  status.innerText = "并行下载中..."

  let done = 0

  // ================= 并行下载 =================
  const results = await asyncPool(4, list, async (item)=>{

    const r = await fetch(`uploads/${id}/${item.name}`)
    const enc = await r.text()

    const decrypted = CryptoJS.AES.decrypt(enc, key)

    const base64 = decrypted.toString(CryptoJS.enc.Base64)

    const binary = atob(base64)

    const arr = new Uint8Array(binary.length)

    for(let i=0;i<binary.length;i++){
      arr[i] = binary.charCodeAt(i)
    }

    done++
    bar.value = (done / list.length) * 100
    status.innerText = `下载 ${done}/${list.length}`

    return {
      index: list.indexOf(item),
      data: arr
    }
  })

  // ================= 排序重组 =================
  results.sort((a,b)=>a.index-b.index)

  let total = 0
  results.forEach(r=> total += r.data.length)

  const merged = new Uint8Array(total)

  let offset = 0

  for(const r of results){
    merged.set(r.data, offset)
    offset += r.data.length
  }

  // ================= 下载文件 =================
  const blob = new Blob([merged])

  const a = document.createElement("a")
  a.href = URL.createObjectURL(blob)
  a.download = originalName

  a.click()

  status.innerText = "下载完成"
  bar.value = 100
}
</script>

</body>
</html>

file.php

<?php

$uploadDir = 'uploads/';
$action = $_GET['action'] ?? '';

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');

function out($data){
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * ======================
 * upload
 * ======================
 */
if($action === 'upload'){

    $id = $_POST['id'] ?? null;
    if(!$id){
        $id = uniqid("f_");
    }

    $dir = $uploadDir . $id;
    if(!is_dir($dir)){
        mkdir($dir, 0755, true);
    }

    // chunk
    if(isset($_POST['chunk']) && isset($_POST['name'])){

        file_put_contents($dir . "/" . $_POST['name'], $_POST['chunk']);

        out([
            "status"=>"ok",
            "type"=>"chunk",
            "id"=>$id
        ]);
    }

    // manifest
    if(isset($_POST['manifest'])){

        file_put_contents($dir . "/manifest.json", $_POST['manifest']);

        out([
            "status"=>"ok",
            "type"=>"manifest",
            "id"=>$id
        ]);
    }

    out(["status"=>"error","msg"=>"invalid"]);
}


/**
 * ======================
 * download
 * ======================
 */
if($action === 'send'){

    $id = $_GET['id'] ?? '';
    $dir = $uploadDir . $id;
    $file = $dir . "/manifest.json";

    if(!file_exists($file)){
        out(["status"=>"error","msg"=>"not found"]);
    }

    $manifest = json_decode(file_get_contents($file), true);

    out([
        "status"=>"ok",
        "manifest"=>$manifest,
        "id"=>$id
    ]);
}