前端大文件上传系统(纯原生JS实现)—— 专治各种不屈服IE9的顽固开发者
各位前端高手们,今天给大家介绍一个能兼容IE9的20G大文件上传系统,确保能让您的客户感动不已(或被吓跑)。毕竟在Vue3盛行的当下,我们还得用原生JS来应对IE9这位“古老神兽”,这种感觉就像是开着法拉利去耕地。
注意:本系统兼容IE9及更高版本浏览器。
var fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = '<span>' + relativePath + '</span> (' + formatFileSize(file.size) + ')';
fileListDiv.appendChild(fileItem);
}
document.getElementById('uploadBtn').disabled = fileQueue.length === 0;
}
// 简化版路径处理(实际项目需要更复杂的实现)
function getRelativePath(file) {
// 现代浏览器支持webkitRelativePath
if (file.webkitRelativePath) {
return file.webkitRelativePath;
}
// IE9及以下...祝你好运
return file.name;
}
// 开始上传
document.getElementById('uploadBtn').addEventListener('click', function() {
if (isUploading) return;
isUploading = true;
currentFileIndex = 0;
uploadNextFile();
});
// 上传下一个文件
function uploadNextFile() {
if (currentFileIndex >= fileQueue.length) {
isUploading = false;
alert('所有文件上传完成!');
return;
}
var fileItem = fileQueue[currentFileIndex];
if (fileItem.status !== 'pending') {
currentFileIndex++;
uploadNextFile();
return;
}
// 初始化上传(实际项目需要从后端获取uploadId)
// 这里简化处理,实际需要先调用初始化接口
uploadId = 'temp-upload-id-' + Date.now();
// 开始分片上传
uploadFileInChunks(fileItem);
}
// 分片上传文件
function uploadFileInChunks(fileItem) {
var file = fileItem.file;
var chunks = fileItem.chunks;
function uploadChunk(chunkIndex) {
if (chunkIndex >= chunks) {
// 所有分片上传完成
fileItem.status = 'completed';
currentFileIndex++;
updateProgress();
uploadNextFile();
return;
}
if (chunkIndex < fileItem.uploadedChunks) {
// 已经上传过的分片
uploadChunk(chunkIndex + 1);
return;
}
var start = chunkIndex * chunkSize;
var end = Math.min(start + chunkSize, file.size);
var chunk = file.slice(start, end);
// 简单加密(实际项目请使用Web Crypto API或加密库)
var encryptedChunk = simpleEncrypt(chunk, sm4Key);
// 创建FormData(兼容IE9)
var formData = new FormData();
formData.append('file', encryptedChunk, 'chunk-' + chunkIndex);
formData.append('uploadId', uploadId);
formData.append('chunkIndex', chunkIndex);
formData.append('totalChunks', chunks);
formData.append('fileName', file.name);
formData.append('relativePath', fileItem.relativePath);
formData.append('fileSize', file.size);
// 创建XMLHttpRequest(兼容IE9)
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/upload', true); // 实际项目中替换为你的后端接口
xhr.onload = function() {
if (xhr.status === 200) {
fileItem.uploadedChunks++;
updateProgress();
uploadChunk(chunkIndex + 1);
} else {
// 上传失败,稍后再试
setTimeout(function() {
uploadChunk(chunkIndex);
}, 1000);
}
};
xhr.onerror = function() {
// 网络故障,稍后再试
setTimeout(function() {
uploadChunk(chunkIndex);
}, 1000);
};
xhr.send(formData);
}
uploadChunk(0);
}
// 简单加密函数(仅作示例,实际项目请采用标准加密库)
function simpleEncrypt(data, key) {
// 这里应是真实的加密实现
// 为示例起见,我们仅返回原始数据
console.log('应加密数据但实际未实现:', data, key);
return data;
}
// 更新进度条
function updateProgress() {
var totalChunks = 0;
var uploadedChunks = 0;
fileQueue.forEach(function(item) {
if (item.status === 'completed') {
uploadedChunks += item.chunks;
} else {
uploadedChunks += item.uploadedChunks;
}
totalChunks += item.chunks;
});
var progress = totalChunks > 0 ? Math.round((uploadedChunks / totalChunks) * 100) : 0;
document.getElementById('progressBar').style.width = progress + '%';
document.getElementById('progressBar').textContent = progress + '%';
}
// 下载功能(简化版)
document.getElementById('downloadBtn').addEventListener('click', function() {
// 实际项目需从后端获取文件列表
alert('下载功能需后端支持,这里仅为示例');
// 示例:下载单个文件(实际需处理文件夹结构)
// window.location.href = '/api/download?fileId=123';
});
// 辅助函数:格式化文件大小
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
var k = 1024;
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// 兼容IE9的console.log(如果控制台未开启)
if (!window.console) {
window.console = {
log: function() {}
};
}
// 初始化时检查本地存储的上传进度(实际项目需更复杂的实现)
function checkLocalProgress() {
// 可在此处添加localStorage或IndexedDB的实现来保存上传进度
console.log('应检查本地存储的上传进度但实际未实现');
}
checkLocalProgress();
项目说明(免责声明版)
IE9兼容性
:此代码可在IE9上运行,但文件夹上传功能将降级为文件选择,因为IE9不支持文件夹选择API。要真正兼容IE9的文件夹上传,你需:
使用Flash或ActiveX控件(已过时)
说服客户升级浏览器(推荐方案)
或开发一个客户端应用(预算100元不足)
加密功能
:示例中的
simpleEncrypt
函数仅为占位符,实际项目请使用:
Web Crypto API(现代浏览器)
CryptoJS等加密库
或让后端处理加密(推荐)
断点续传
示例中简化了实现,实际上需要:
- 后端支持片段验证
- 本地储存上传状态(利用localStorage或IndexedDB)
- 更详尽的错误处理与重试策略
- 20GB文件的支持
此示例可以运行,但在实际项目中还需考虑:
- 内存管理(大型文件分段加载)
- 超时管理
- 服务器配置(例如Nginx/Apache的超时设定)
预算说明
100元预算开发这套系统等同于:
建议至少提高2-3倍的预算。
加入我们的接单群
虽然我无法无偿协助你完成整个项目,但欢迎加入我们的前端接单群(QQ群:374992201),在这里你可以:
- 寻找到合作开发项目的伙伴
- 分享技术资料和外包机遇
- 参与我们的“推荐返现”活动(确实有奖金)
- 领取入群红包(1-99元,取决于运气)
请记住,在编程领域,没有免费的午餐,但有免费的群聊和偶尔出现的红包!
将组件复制到项目中
示例中已包含该目录
引入组件
配置接口地址
接口地址分别对应:文件初始化,文件数据上传,文件进度,文件上传结束,文件移除,文件夹初始化,文件夹移除,文件列表
参考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de
处理事件
启动测试
启动成功
效果
数据库
效果预览
文件上传
文件刷新续传
支持离线保存文件进度,在关闭或刷新浏览器后不会丢失,仍能继续上传
文件夹上传
支持上传文件夹并保持层级结构,同时支持离线保存进度信息,即使刷新页面、关闭页面或重启系统也不会丢失上传进度。
批量下载
支持多文件同时下载
下载续传
文件下载支持离线保存进度信息,即使刷新页面、关闭页面或重启系统也不会丢失进度信息。
文件夹下载
支持下载文件夹,并保持层级结构,无需打包,不占用服务器资源。
下载示例
点击下载完整示例