全部版块 我的主页
论坛 数据科学与人工智能 IT基础
113 0
2025-11-18

前端大文件上传系统(纯原生JS实现)—— 专治各种不屈服IE9的顽固开发者

各位前端高手们,今天给大家介绍一个能兼容IE9的20G大文件上传系统,确保能让您的客户感动不已(或被吓跑)。毕竟在Vue3盛行的当下,我们还得用原生JS来应对IE9这位“古老神兽”,这种感觉就像是开着法拉利去耕地。

注意:本系统兼容IE9及更高版本浏览器。
0%

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

处理事件

启动测试

启动成功

效果

数据库

效果预览

文件上传

文件刷新续传

支持离线保存文件进度,在关闭或刷新浏览器后不会丢失,仍能继续上传

文件夹上传

支持上传文件夹并保持层级结构,同时支持离线保存进度信息,即使刷新页面、关闭页面或重启系统也不会丢失上传进度。

批量下载

支持多文件同时下载

下载续传

文件下载支持离线保存进度信息,即使刷新页面、关闭页面或重启系统也不会丢失进度信息。

文件夹下载

支持下载文件夹,并保持层级结构,无需打包,不占用服务器资源。

下载示例

点击下载完整示例

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群