news 2026/2/17 15:25:37

JS文件批量下载并打包成ZIP的功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JS文件批量下载并打包成ZIP的功能

方法一:使用JSZip和FileSaver(推荐)

1. 安装依赖

npm install jszip file-saver # 或使用CDN

2. HTML结构

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>JS文件批量下载</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script> <style> .container { max-width: 800px; margin: 0 auto; padding: 20px; } .file-list { margin: 20px 0; padding: 10px; border: 1px solid #ddd; max-height: 300px; overflow-y: auto; } .file-item { display: flex; justify-content: space-between; align-items: center; padding: 8px; border-bottom: 1px solid #eee; } .progress-bar { width: 100%; height: 20px; background-color: #f0f0f0; border-radius: 10px; margin: 10px 0; overflow: hidden; } .progress { height: 100%; background-color: #4CAF50; width: 0%; transition: width 0.3s; } button { background-color: #4CAF50; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; } button:hover { background-color: #45a049; } button:disabled { background-color: #cccccc; cursor: not-allowed; } </style> </head> <body> <div class="container"> <h1>JS文件批量下载器</h1> <!-- 文件输入区域 --> <div> <h3>选择JS文件</h3> <input type="file" id="fileInput" multiple accept=".js" /> <button onclick="addFiles()">添加文件</button> </div> <!-- URL输入区域 --> <div style="margin-top: 20px;"> <h3>或输入JS文件URL</h3> <div style="display: flex; gap: 10px;"> <input type="text" id="urlInput" placeholder="输入JS文件URL" style="flex: 1; padding: 8px;" /> <button onclick="addURL()">添加URL</button> </div> </div> <!-- 文件列表 --> <div class="file-list" id="fileList"> <p>已选择文件:<span id="fileCount">0</span>个</p> </div> <!-- 进度条 --> <div id="progressContainer" style="display: none;"> <div class="progress-bar"> <div class="progress" id="progress"></div> </div> <p id="progressText">准备中...</p> </div> <!-- 下载按钮 --> <div style="margin-top: 20px;"> <button onclick="downloadAllAsZip()" id="downloadBtn" disabled>打包下载ZIP</button> <button onclick="clearFiles()" style="background-color: #f44336; margin-left: 10px;">清空列表</button> </div> </div> <script src="main.js"></script> </body> </html>

3. JavaScript主逻辑 (main.js)

let files = []; let fileCounter = 1; // 添加本地文件 function addFiles() { const fileInput = document.getElementById('fileInput'); const selectedFiles = Array.from(fileInput.files); selectedFiles.forEach(file => { if (file.type === 'application/javascript' || file.name.endsWith('.js')) { files.push({ id: fileCounter++, name: file.name, content: file, type: 'local' }); } }); updateFileList(); fileInput.value = ''; } // 添加URL文件 async function addURL() { const urlInput = document.getElementById('urlInput'); const url = urlInput.value.trim(); if (!url) { alert('请输入有效的URL'); return; } if (!url.endsWith('.js')) { alert('请输入JS文件的URL'); return; } // 从URL提取文件名 const fileName = url.split('/').pop() || `file_${fileCounter}.js`; files.push({ id: fileCounter++, name: fileName, url: url, type: 'url' }); updateFileList(); urlInput.value = ''; } // 更新文件列表显示 function updateFileList() { const fileList = document.getElementById('fileList'); const fileCount = document.getElementById('fileCount'); const downloadBtn = document.getElementById('downloadBtn'); fileList.innerHTML = '<p>已选择文件:<span id="fileCount">' + files.length + '</span>个</p>'; files.forEach(file => { const div = document.createElement('div'); div.className = 'file-item'; div.innerHTML = ` <span>${file.name}</span> <button onclick="removeFile(${file.id})" style="background-color: #ff4444; padding: 4px 8px; font-size: 12px;"> 删除 </button> `; fileList.appendChild(div); }); fileCount.textContent = files.length; downloadBtn.disabled = files.length === 0; } // 移除文件 function removeFile(id) { files = files.filter(file => file.id !== id); updateFileList(); } // 清空所有文件 function clearFiles() { if (confirm('确定要清空所有文件吗?')) { files = []; updateFileList(); } } // 主下载函数 async function downloadAllAsZip() { if (files.length === 0) { alert('请先添加文件'); return; } const progressContainer = document.getElementById('progressContainer'); const progressBar = document.getElementById('progress'); const progressText = document.getElementById('progressText'); const downloadBtn = document.getElementById('downloadBtn'); // 显示进度条 progressContainer.style.display = 'block'; downloadBtn.disabled = true; try { const zip = new JSZip(); let processed = 0; // 处理每个文件 for (const file of files) { progressText.textContent = `正在处理: ${file.name} (${processed + 1}/${files.length})`; if (file.type === 'local') { // 本地文件 const content = await readFileAsText(file.content); zip.file(file.name, content); } else if (file.type === 'url') { // 远程文件 try { const response = await fetch(file.url); if (!response.ok) { throw new Error(`下载失败: ${response.status} ${response.statusText}`); } const content = await response.text(); zip.file(file.name, content); } catch (error) { console.error(`下载 ${file.url} 失败:`, error); zip.file(file.name, `// 下载失败: ${error.message}\n// 原始URL: ${file.url}`); } } processed++; const progressPercent = (processed / files.length) * 100; progressBar.style.width = `${progressPercent}%`; } // 生成ZIP文件 progressText.textContent = '正在生成ZIP文件...'; const zipBlob = await zip.generateAsync({ type: 'blob', compression: 'DEFLATE', compressionOptions: { level: 6 } }, (metadata) => { if (metadata.percent) { progressBar.style.width = `${metadata.percent}%`; progressText.textContent = `正在压缩: ${Math.round(metadata.percent)}%`; } }); // 下载ZIP文件 progressText.textContent = '正在下载...'; saveAs(zipBlob, `js-files-${new Date().toISOString().slice(0, 10)}.zip`); progressText.textContent = '下载完成!'; setTimeout(() => { progressContainer.style.display = 'none'; progressBar.style.width = '0%'; downloadBtn.disabled = false; }, 2000); } catch (error) { console.error('打包失败:', error); alert(`打包失败: ${error.message}`); progressContainer.style.display = 'none'; downloadBtn.disabled = false; } } // 读取本地文件为文本 function readFileAsText(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => resolve(e.target.result); reader.onerror = (e) => reject(new Error('文件读取失败')); reader.readAsText(file); }); }

方法二:使用StreamSaver处理大文件

如果需要处理非常大的文件,可以使用StreamSaver:

<!-- 在head中添加 --> <script src="https://cdn.jsdelivr.net/npm/web-streams-polyfill@2.0.2/dist/ponyfill.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/streamsaver@2.0.3/StreamSaver.min.js"></script>
// 替换之前的下载函数 async function downloadLargeFilesAsZip() { if (files.length === 0) return; // 创建可写流 const fileStream = streamSaver.createWriteStream('js-files.zip'); const writer = fileStream.getWriter(); // 使用JSZip生成流 const zip = new JSZip(); // 添加文件到zip... // ... 处理文件逻辑 // 生成并写入流 zip.generateInternalStream({ type: 'blob', streamFiles: true }).on('data', (chunk) => { writer.write(chunk); }).on('end', () => { writer.close(); }).resume(); }

方法三:使用Node.js后端打包

如果需要处理大量文件或跨域问题,可以使用Node.js后端:

// server.js const express = require('express'); const archiver = require('archiver'); const axios = require('axios'); const app = express(); app.post('/download-js', async (req, res) => { const { urls } = req.body; res.setHeader('Content-Type', 'application/zip'); res.setHeader('Content-Disposition', 'attachment; filename=js-files.zip'); const archive = archiver('zip', { zlib: { level: 9 } }); archive.pipe(res); for (const url of urls) { try { const response = await axios.get(url, { responseType: 'stream' }); const filename = url.split('/').pop(); archive.append(response.data, { name: filename }); } catch (error) { console.error(`Failed to fetch ${url}:`, error); } } archive.finalize(); }); app.listen(3000, () => { console.log('Server running on port 3000'); });

使用说明

  1. 本地文件:选择本地的JS文件

  2. 远程文件:输入JS文件的URL地址

  3. 打包下载:点击"打包下载ZIP"按钮

  4. 清空列表:点击"清空列表"按钮移除所有文件

注意事项

  1. 跨域问题:如果JS文件来自不同源且没有CORS头,可能无法下载

  2. 文件大小:前端处理大量大文件时可能内存不足

  3. 浏览器兼容性:现代浏览器支持良好,IE需要polyfill

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/14 5:41:23

FPGA实战:一段让我重新认识时序收敛的FPGA迁移之旅

从Kintex-7到Versal&#xff1a;一段让我重新认识时序收敛的FPGA迁移之旅 摘要 &#xff1a;当一段在Kintex-7上稳定运行多年的MIPI Rx代码&#xff0c;迁移到Versal后开始随机出错&#xff0c;我没想到问题竟隐藏在一个看似"安全"的buffer逻辑中。这是一个关于时钟域…

作者头像 李华
网站建设 2026/2/16 6:12:24

YOLOv8+PyQt5农作物杂草检测(可以重新训练模型,yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)

资源包含可视化的农作物杂草检测系统&#xff0c;基于最新的YOLOv8训练的农作物杂草检测模型&#xff0c;和基于PyQt5制作的可视化农作物杂草检测系统&#xff0c;包含登陆页面、注册页面和检测页面&#xff0c;该系统可自动检测和识别图片或视频当中出现的农作和物杂草&#x…

作者头像 李华
网站建设 2026/2/14 2:02:44

OpenCore Legacy Patcher终极指南:让老Mac重获新生的10个技巧

OpenCore Legacy Patcher终极指南&#xff1a;让老Mac重获新生的10个技巧 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher是一款革命性的开源工具…

作者头像 李华
网站建设 2026/2/4 11:09:33

云顶之弈智能助手:一键自动化挂机完全指南

云顶之弈智能助手&#xff1a;一键自动化挂机完全指南 【免费下载链接】LOL-Yun-Ding-Zhi-Yi 英雄联盟 云顶之弈 全自动挂机刷经验程序 外挂 脚本 ,下载慢可以到https://gitee.com/stringify/LOL-Yun-Ding-Zhi-Yi 项目地址: https://gitcode.com/gh_mirrors/lo/LOL-Yun-Ding-…

作者头像 李华
网站建设 2026/2/17 9:32:11

智能运动管理高效方案:轻松实现自动化步数同步

智能运动管理高效方案&#xff1a;轻松实现自动化步数同步 【免费下载链接】mimotion 小米运动刷步数&#xff08;微信支付宝&#xff09;支持邮箱登录 项目地址: https://gitcode.com/gh_mirrors/mimo/mimotion 想要告别手动记录运动数据的烦恼&#xff0c;让智能技术为…

作者头像 李华
网站建设 2026/2/15 18:29:24

Java 抽象类

Java 抽象类 引言 在Java编程语言中,抽象类是一种特殊的类,它用于定义一个或多个抽象方法,这些方法在子类中必须被实现。抽象类是面向对象编程中一个非常重要的概念,它允许开发者定义一个通用接口,而具体的实现细节则由子类提供。本文将深入探讨Java抽象类的概念、特点、…

作者头像 李华