柯里化本身不直接处理文件上传或分片,而是将多参数函数转为单参数函数链,用于预配置URL、token、分片大小、并发数、重试策略等不变参数,生成可复用的专用上传函数。

JavaScript 中的柯里化本身不直接处理文件上传或分片,它是一种函数式编程技巧,用于将多参数函数转换为一系列单参数函数。要实现“文件上传分片”的功能,核心是切片(slice)、并发控制、进度管理、服务端配合等;而柯里化可用来优雅地预配置上传行为,比如固定 URL、token、分片大小、重试策略等,再生成专用的上传函数。
1. 柯里化封装分片上传配置
把上传所需的不变参数(如接口地址、认证头、分片大小)通过柯里化预先固化,返回一个可传入文件和元信息的函数:
const createChunkUploader = (baseUrl, token, chunkSize = 1024 * 1024) =>
(file, { uploadId, fileName, onProgress } = {}) => {
const totalSize = file.size;
const chunks = [];
let start = 0;
<pre class="brush:php;toolbar:false;">while (start <p>};</p>使用时只需一次配置,多次复用:
const myUploader = createChunkUploader(
'https://api.example.com/upload',
'Bearer abc123',
5 * 1024 * 1024 // 5MB 分片
);
<p>// 后续上传不同文件,无需重复传 baseUrl/token
myUploader(fileA, { uploadId: 'id-1', fileName: 'a.pdf' });
myUploader(fileB, { uploadId: 'id-2', fileName: 'b.zip' });</p>2. 柯里化 + 并发控制(如 Promise.allSettled + 限流)
分片上传常需限制同时上传的请求数(如最多 3 个并发),可用柯里化把并发数和请求工厂函数绑定:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const createLimitedChunkUploader = (maxConcurrency) =>
(uploadFn) => async (chunks, options) => {
const results = [];
const executing = [];
<pre class="brush:php;toolbar:false;">for (const chunk of chunks) {
const task = uploadFn(chunk, options)
.then(res => ({ status: 'fulfilled', value: res }))
.catch(err => ({ status: 'rejected', reason: err }));
results.push(task);
executing.push(task);
if (executing.length >= maxConcurrency) {
await Promise.race(executing);
executing.splice(0, 1); // 移除最先完成的一个
}
}
return Promise.allSettled(results);};
// 组合使用 const uploadWith3Concurrency = createLimitedChunkUploader(3)(uploadSingleChunk); await uploadWith3Concurrency(chunks, { / ... / });
3. 柯里化处理重试与错误恢复
对单个分片上传函数添加自动重试能力,并通过柯里化固化重试次数和延迟:
const createRetryableUpload = (maxRetries = 3, baseDelay = 1000) =>
async (chunk, options) => {
let lastError;
for (let i = 0; i setTimeout(r, baseDelay * Math.pow(2, i))); // 指数退避
}
}
}
throw lastError;
};
<p>// 生成带重试的上传器
const robustUpload = createRetryableUpload(2, 500);
await robustUpload(file.slice(0, 1024*1024), { url: '/chunk', headers: { token } });</p>4. 实际分片上传关键补充点(非柯里化但必须)
柯里化只是组织逻辑的手段,真正完成分片上传还需以下支撑:
-
前端切片:用
File.prototype.slice()(注意兼容性,推荐用Blob.prototype.slice()) -
唯一标识:为每个文件生成 hash(如 SparkMD5)或服务端分配
uploadId,避免重复上传相同文件 -
分片元数据:每个请求携带
chunkIndex、totalChunks、fileName、uploadId等,便于服务端合并 - 断点续传:上传前先查服务端已传哪些分片(GET /upload/{id}/chunks),跳过已成功分片
-
合并触发:所有分片成功后,调用
MERGE接口通知服务端拼接
柯里化不是银弹,但它让配置分离、函数复用、测试隔离变得更自然。把“变”(文件、进度回调)和“不变”(域名、鉴权、策略)解耦,才是它在分片上传中真正的价值。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










