plus.downloader.createDownload 发送 POST 请求并携带 token
/**
* 创建下载任务
* @param {string} url - 下载地址
* @param {Object} params - POST参数
* @param {Object} [options] - 下载配置选项
* @returns {Promise} 下载结果Promise
*/
export const createPostDownload = (url, params, options = {}) => {
return new Promise((resolve, reject) => {
try {
// 默认配置
const defaultOptions = {
method: 'POST',
filename: '_downloads/',
timeout: 120,
retry: 1,
...options
}
const headers = {
'Content-Type': 'application/json',
Accept: '*/*',
...options.headers
}
console.log('开始下载,参数:', {
url,
params,
headers
})
// 创建下载任务
const downloadTask = plus.downloader.createDownload(
url,
{
...defaultOptions,
// 使用数组形式设置请求头
headers,
data: JSON.stringify(params)
},
(download, status) => {
console.log('下载完成回调:', status, download)
if (status === 200) {
resolve({
status,
filename: download.filename,
totalSize: download.totalSize,
downloadedSize: download.downloadedSize
})
} else {
reject(
new Error(`Download failed with status: ${status}`)
)
}
}
)
// 设置请求头
for (const name in headers) {
downloadTask.setRequestHeader(name, headers[name])
}
// 监听状态变化
downloadTask.addEventListener('statechanged', (task, status) => {
console.log('状态变化:', {
status,
state: task.state,
downloadedSize: task.downloadedSize,
totalSize: task.totalSize
})
// 处理不同的下载状态
switch (task.state) {
case 1: // 开始
console.log('开始下载')
break
case 2: // 下载中
handleProgress(task)
break
case 3: // 完成
console.log('下载完成')
break
case 4: // 暂停
console.log('下载暂停')
break
case -1: // 错误
handleError(task)
break
}
})
// 处理进度
const handleProgress = (task) => {
if (typeof options.onProgress === 'function') {
const progress =
task.totalSize > 0
? Math.floor(
(task.downloadedSize / task.totalSize) * 100
)
: 0
options.onProgress({
progress: Math.min(100, Math.max(0, progress)),
downloadedSize: task.downloadedSize,
totalSize: task.totalSize,
state: task.state
})
}
}
// 处理错误
const handleError = (task) => {
console.error('下载错误:', task)
reject(new Error('Download failed'))
// 可以尝试重新下载
if (defaultOptions.retry > 0) {
console.log('尝试重新下载...')
defaultOptions.retry--
task.abort()
setTimeout(() => {
task.start()
}, 1000)
}
}
// 设置超时
const timeout = setTimeout(() => {
console.log('下载超时')
downloadTask.abort()
reject(new Error('Download timeout'))
}, defaultOptions.timeout * 1000)
// 开始下载
console.log('启动下载任务')
downloadTask.start()
// downloadTask.sendData(JSON.stringify(params))
} catch (error) {
console.error('下载过程出错:', error)
reject(error)
}
})
}
使用实例
// 使用示例
const downloadFile = async () => {
try {
const url = 'https://api.example.com/download';
const params = {
fileId: '123'
};
await createPostDownload(url, params, {
filename: '_downloads/myfile.pdf',
onProgress: (info) => {
if (info.indeterminate) {
console.log(`正在下载...已下载: ${info.downloadedSize} bytes`);
} else {
console.log(`下载进度:${info.progress}%`);
console.log(`已下载:${info.downloadedSize} / ${info.totalSize} bytes`);
}
// 根据状态显示不同信息
switch(info.state) {
case 1:
console.log('开始下载');
break;
case 2:
console.log('正在下载');
break;
case 3:
console.log('下载完成');
break;
case 4:
console.log('下载暂停');
break;
}
}
});
console.log('下载成功');
} catch (error) {
console.error('下载失败:', error);
}
};
// 带进度条的UI示例
const downloadWithProgressBar = async () => {
const progressBar = document.querySelector('.progress-bar');
const progressText = document.querySelector('.progress-text');
try {
await createPostDownload(url, params, {
filename: '_downloads/myfile.pdf',
onProgress: (info) => {
if (!info.indeterminate) {
// 更新进度条
progressBar.style.width = `${info.progress}%`;
progressText.textContent = `${info.progress}%`;
// 添加下载速度计算
const speed = calculateSpeed(info.downloadedSize, Date.now());
const speedText = formatSpeed(speed);
progressText.textContent =
`${info.progress}% - ${speedText}`;
} else {
progressText.textContent = '准备下载...';
}
}
});
} catch (error) {
progressText.textContent = '下载失败';
console.error(error);
}
};
// 下载速度计算辅助函数
let lastSize = 0;
let lastTime = Date.now();
function calculateSpeed(currentSize, currentTime) {
const sizeDiff = currentSize - lastSize;
const timeDiff = currentTime - lastTime;
lastSize = currentSize;
lastTime = currentTime;
return timeDiff > 0 ? (sizeDiff / timeDiff) * 1000 : 0; // bytes per second
}
function formatSpeed(bytesPerSecond) {
if (bytesPerSecond < 1024) return `${bytesPerSecond.toFixed(1)} B/s`;
if (bytesPerSecond < 1024 * 1024) return `${(bytesPerSecond / 1024).toFixed(1)} KB/s`;
return `${(bytesPerSecond / (1024 * 1024)).toFixed(1)} MB/s`;
}