【前端批量下載圖片,并打包成壓縮包下載】

一、需求說明

我現在有個需求:
1.列表中有個下載按鈕,點擊下載,將列表中所有的圖片打成壓縮包,并下載
2.效果演示點擊查看效果

在這里插入圖片描述
最終效果:
在這里插入圖片描述

二、安裝下載插件

實現此功能需要兩個插件:jszip、file-saver
如名字簡易理解:一個是可以打成壓縮包,另一個是可以保存下載的

// 安裝下載
npm install jszip
npm install file-saver --save

三、引入插件

//npm引入方式
import JSZip from 'jszip'
import { saveAs } from 'file-saver'
//cdn引入方式
<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>

四、代碼實現

話不多說,上代碼,為了方便,以下代碼直接復制即可實現效果,后續自己修改也可

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>圖片URL批量下載工具</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>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);min-height: 100vh;padding: 20px;}.container {max-width: 1200px;margin: 0 auto;background: white;border-radius: 15px;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);overflow: hidden;}header {background: linear-gradient(90deg, #3498db, #8e44ad);color: white;padding: 25px 40px;text-align: center;}h1 {font-size: 2.5rem;margin-bottom: 10px;letter-spacing: 1px;}.subtitle {font-size: 1.1rem;opacity: 0.9;max-width: 700px;margin: 0 auto;}.content {padding: 30px;display: grid;grid-template-columns: 1fr 350px;gap: 30px;}.image-grid {display: grid;grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));gap: 20px;}.image-card {background: white;border-radius: 10px;overflow: hidden;box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);transition: all 0.3s ease;}.image-card:hover {transform: translateY(-5px);box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);}.image-preview {height: 180px;background-color: #f8f9fa;display: flex;align-items: center;justify-content: center;overflow: hidden;}.image-preview img {max-width: 100%;max-height: 100%;object-fit: cover;transition: transform 0.3s ease;}.image-card:hover .image-preview img {transform: scale(1.05);}.image-info {padding: 15px;}.image-info h3 {font-size: 1.1rem;margin-bottom: 8px;color: #2c3e50;}.image-url {font-size: 0.85rem;color: #7f8c8d;word-break: break-all;line-height: 1.4;}.control-panel {background: #f8f9fa;border-radius: 12px;padding: 25px;box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);}.control-panel h2 {color: #2c3e50;margin-bottom: 20px;padding-bottom: 15px;border-bottom: 1px solid #e0e0e0;}.stats {background: white;border-radius: 10px;padding: 15px;margin-bottom: 25px;box-shadow: 0 3px 10px rgba(0, 0, 0, 0.05);}.stat-item {display: flex;justify-content: space-between;margin-bottom: 10px;padding-bottom: 10px;border-bottom: 1px solid #f0f0f0;}.stat-item:last-child {margin-bottom: 0;padding-bottom: 0;border: none;}.progress-container {margin: 25px 0;}.progress-label {display: flex;justify-content: space-between;margin-bottom: 8px;font-size: 0.9rem;color: #7f8c8d;}.progress-bar {height: 10px;background: #e0e0e0;border-radius: 5px;overflow: hidden;}.progress-fill {height: 100%;background: linear-gradient(90deg, #3498db, #8e44ad);border-radius: 5px;width: 0%;transition: width 0.5s ease;}.download-btn {display: block;width: 100%;padding: 15px;background: linear-gradient(90deg, #3498db, #8e44ad);color: white;border: none;border-radius: 8px;font-size: 1.1rem;font-weight: 600;cursor: pointer;transition: all 0.3s ease;box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3);}.download-btn:hover {transform: translateY(-3px);box-shadow: 0 8px 20px rgba(52, 152, 219, 0.4);}.download-btn:active {transform: translateY(0);}.download-btn:disabled {background: #bdc3c7;transform: none;box-shadow: none;cursor: not-allowed;}.status-message {margin-top: 20px;padding: 12px;border-radius: 8px;text-align: center;font-weight: 500;display: none;}.success {background: #e8f6ef;color: #27ae60;display: block;}.error {background: #fdecea;color: #e74c3c;display: block;}footer {text-align: center;padding: 20px;color: #7f8c8d;font-size: 0.9rem;border-top: 1px solid #eee;}@media (max-width: 900px) {.content {grid-template-columns: 1fr;}}</style>
</head>
<body><div class="container"><header><h1>圖片URL批量下載工具</h1><p class="subtitle">將列表中的圖片URL批量下載并打包成壓縮包,支持預覽和進度顯示</p></header><div class="content"><div class="image-grid" id="imageGrid"><!-- 圖片卡片將通過JS動態生成 --></div><div class="control-panel"><h2>下載控制面板</h2><div class="stats"><div class="stat-item"><span>圖片總數:</span><span id="totalCount">0</span></div><div class="stat-item"><span>下載進度:</span><span id="progressCount">0/0</span></div><div class="stat-item"><span>壓縮包大小:</span><span id="zipSize">0 MB</span></div></div><div class="progress-container"><div class="progress-label"><span>下載進度</span><span id="progressPercent">0%</span></div><div class="progress-bar"><div class="progress-fill" id="progressFill"></div></div></div><button id="downloadBtn" class="download-btn">下載所有圖片(ZIP壓縮包)</button><div id="statusMessage" class="status-message"></div></div></div><footer><p>? 2023 圖片批量下載工具 | 支持多格式圖片下載 | 使用JSZip實現壓縮功能</p></footer></div><script>// 示例圖片數據const imageList = [{ id: 1, title: "山脈風景", url: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" },{ id: 2, title: "海灘日落", url: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" },{ id: 3, title: "森林小徑", url: "https://images.unsplash.com/photo-1448375240586-882707db888b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" },{ id: 4, title: "城市夜景", url: "https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80" }];// DOM元素const imageGrid = document.getElementById('imageGrid');const downloadBtn = document.getElementById('downloadBtn');const totalCountEl = document.getElementById('totalCount');const progressCountEl = document.getElementById('progressCount');const zipSizeEl = document.getElementById('zipSize');const progressPercentEl = document.getElementById('progressPercent');const progressFillEl = document.getElementById('progressFill');const statusMessageEl = document.getElementById('statusMessage');// 渲染圖片列表function renderImageList() {imageGrid.innerHTML = '';imageList.forEach(image => {const card = document.createElement('div');card.className = 'image-card';card.innerHTML = `<div class="image-preview"><img src="${image.url}" alt="${image.title}" loading="lazy"></div><div class="image-info"><h3>${image.title}</h3><p class="image-url">${image.url}</p></div>`;imageGrid.appendChild(card);});totalCountEl.textContent = imageList.length;progressCountEl.textContent = `0/${imageList.length}`;}// 獲取安全的文件名function getSafeFilename(url, id, title, blob) {try {// 嘗試從URL中提取文件名const urlObj = new URL(url);const pathParts = urlObj.pathname.split('/');let filename = pathParts.pop() || `image_${id}`;// 移除查詢參數部分filename = filename.split('?')[0];// 檢查是否有文件擴展名const hasExtension = filename.includes('.') && filename.lastIndexOf('.') > filename.lastIndexOf('/');// 如果沒有擴展名,從blob類型獲取if (!hasExtension) {const extension = blob.type.split('/')[1] || 'jpg';filename += `.${extension}`;}// 清理文件名中的特殊字符filename = filename.replace(/[^a-z0-9_.-]/gi, '_');// 添加標題前綴使文件名更易讀const cleanTitle = title.replace(/[^a-z0-9\s]/gi, '').replace(/\s+/g, '_').substring(0, 20);return `${cleanTitle}_${filename}`;} catch (e) {// 如果URL解析失敗,使用默認文件名return `image_${id}.jpg`;}}// 下載所有圖片并打包成ZIPasync function downloadImagesAsZip() {try {// 重置狀態statusMessageEl.className = 'status-message';downloadBtn.disabled = true;downloadBtn.textContent = '下載中...';// 創建JSZip實例const zip = new JSZip();const folder = zip.folder("images");let downloadedCount = 0;// 更新進度function updateProgress() {downloadedCount++;const percent = Math.round((downloadedCount / imageList.length) * 100);progressCountEl.textContent = `${downloadedCount}/${imageList.length}`;progressPercentEl.textContent = `${percent}%`;progressFillEl.style.width = `${percent}%`;}// 下載所有圖片for (const image of imageList) {try {// 獲取圖片const response = await fetch(image.url);if (!response.ok) throw new Error(`HTTP錯誤! 狀態碼: ${response.status}`);// 獲取圖片Blobconst blob = await response.blob();// 獲取安全的文件名const filename = getSafeFilename(image.url, image.id, image.title, blob);// 將圖片添加到ZIPfolder.file(filename, blob);updateProgress();} catch (error) {console.error(`下載失敗: ${image.url}`, error);updateProgress();}}// 生成ZIP文件const content = await zip.generateAsync({type: "blob"}, metadata => {const sizeInMB = (metadata.currentZipSize / (1024 * 1024)).toFixed(2);zipSizeEl.textContent = `${sizeInMB} MB`;});// 下載ZIP文件saveAs(content, "downloaded_images.zip");// 更新狀態statusMessageEl.textContent = '下載成功!壓縮包已開始下載';statusMessageEl.className = 'status-message success';} catch (error) {console.error('打包過程中出錯:', error);statusMessageEl.textContent = '下載失敗:' + error.message;statusMessageEl.className = 'status-message error';} finally {downloadBtn.disabled = false;downloadBtn.textContent = '下載所有圖片(ZIP壓縮包)';}}// 初始化頁面document.addEventListener('DOMContentLoaded', () => {renderImageList();downloadBtn.addEventListener('click', downloadImagesAsZip);});</script>
</body>
</html>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/87431.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87431.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87431.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

NV133NV137美光固態閃存NV147NV148

NV133NV137美光固態閃存NV147NV148 美光固態閃存技術矩陣深度解析&#xff1a;NV133至NV148的全面較量 一、性能參數&#xff1a;數據高速公路的“車速”比拼 讀寫速度&#xff1a;從“鄉間小道”到“高鐵動脈” 美光NV系列固態閃存的核心競爭力在于其讀寫速度的躍升。以NV15…

從LLM到WM:大語言模型如何進化成具身世界模型?

1.引言這學期在方老師開設的《機器人大模型基礎和前沿》選修課上接觸并學習了具身智能方面的相關知識。作為交互組的組長&#xff0c;我和組員們在幻爾機器狗的功能開發上有切身的實踐與探索&#xff0c;在張江具身智能大會上&#xff0c;也見識到了前沿的技術和行業的發展現狀…

第十六屆藍橋杯C++B組國賽題解+復盤總結

文章目錄 寫在前面1、新型鎖2、互質藏卡3、數字輪盤4、斐波那契字符串5、項鏈排列6、藍橋星數字7、翻倍8、近似回文字符串9、子串去重10、涂格子 寫在前面 打了三年&#xff0c;第十六屆是我最后一次參加了&#xff0c;終于如愿以償國一啦。 這場的大多題目都補了&#xff0c;…

【TTS】2024-2025年主流開源TTS模型的綜合對比分析

以下是針對2024-2025年主流開源與商用TTS模型的綜合技術選型分析&#xff0c;結合GitHub熱度、功能特性、部署成本及中文支持等核心維度進行對比&#xff0c;并附詳細實踐建議。 一、開源TTS模型對比&#xff08;2024-2025年主流方案&#xff09; 模型名稱開源/廠商克隆支持中…

redis延時雙刪,為什么第一次刪除

Redis延時雙刪策略中第一次刪除的作用 在緩存與數據庫一致性方案中&#xff0c;"延時雙刪"&#xff08;Delayed Double-Delete&#xff09;是一種經典策略&#xff0c;其核心流程如下&#xff1a; 第一次刪除&#xff1a;更新數據庫前&#xff0c;先刪除緩存 更新數…

深度學習1(深度學習和機器學習的區別,神經網絡)

深度學習和機器學習的區別 深度學習和機器學習都是人工智能&#xff08;AI&#xff09;的重要分支&#xff0c;但它們在方法、應用場景和技術細節上有顯著區別。 機器學習通過算法讓計算機從數據中學習規律&#xff0c;并做出預測或決策。核心是特征工程&#xff08;人工提取數…

這才叫窗口查詢!TDEngine官方文檔沒講透的實戰玩法

第1章&#xff1a;你不知道的TDEngine窗口查詢——開局就不簡單 先別急著翻白眼&#xff0c;提到時間窗口查詢&#xff0c;可能你腦子里立馬浮現的就是那些常規套路&#xff1a;GROUP BY time_interval、FIRST()、LAST()&#xff0c;再加上點AVG()和MAX()&#xff0c;一鍋端。…

Day50 預訓練模型+CBAM模塊

目錄 一、resnet結構解析 二、CBAM放置位置的思考 三、針對預訓練模型的訓練策略 a.差異化學習率 b.三階段式解凍與微調 (Progressive Unfreezing) 四、嘗試對vgg16cbam進行微調策略 是否可以對于預訓練模型增加模塊來優化其效果&#xff0c;這里會遇到一個問題&#xff…

快速說一下TDD BDD DDD

基本概念 TDD&#xff08;測試驅動開發&#xff09;、BDD&#xff08;行為驅動開發&#xff09;和 DDD&#xff08;領域驅動設計&#xff09;是軟件開發領域中幾個重要的概念&#xff0c;它們各自有著獨特的側重點與應用場景&#xff0c;以下為你詳細介紹&#xff1a; 測試驅…

淺析基于深度學習算法的英文OCR技術工作原理及其應用場景

在數字化信息飛速發展的當下&#xff0c;大量的文本信息以各種形式存在&#xff0c;從傳統的紙質文檔到電子圖片中的文字內容。如何高效地將這些非結構化的文本轉化為計算機能夠理解和處理的格式&#xff0c;成為了提高信息處理效率的關鍵。英文 OCR&#xff08;Optical Charac…

AI時代SEO關鍵詞策略

內容概要 在人工智能&#xff08;AI&#xff09;驅動的新時代&#xff0c;搜索引擎優化&#xff08;SEO&#xff09;關鍵詞策略正迎來顛覆性變革。本篇文章將系統解析AI技術如何重塑關鍵詞研究、內容優化及流量提升的全過程&#xff0c;幫助企業實現高效可持續的在線曝光。通過…

免費一鍵自動化申請、續期、部署、監控所有 SSL/TLS 證書,ALLinSSL開源免費的 SSL 證書自動化管理平臺

目錄 一、前言二、ALLinSSL 簡介亮點核心功能 三、操作步驟部署安裝授權DNS服務商授權你的主機服務器自動化部署ssl測試自動申請ssl證書 一、前言 SSL證書是每個網站必備的&#xff0c;但是現在的免費的ssl證書有效期是3個月&#xff0c;以后CA/B Forum 調整 SSL 證書最長有效期…

如何高效清理C盤、釋放存儲空間,讓電腦不再卡頓。

以下是針對Windows系統的C盤深度清理全攻略&#xff0c;包含系統級優化和進階操作&#xff0c;可釋放30%-70%的冗余空間&#xff1a; 一、系統自帶工具快速清理&#xff08;5分鐘見效&#xff09; 磁盤清理工具 按WinR → 輸入cleanmgr → 選擇C盤重點勾選&#xff1a; ? Wind…

AI 如何批量提取 Word 表格中的字段數據到 Excel 中?

在日常工作中&#xff0c;我們經常會接觸到大量 Word 表格——學生登記表、客戶信息表、報名信息表……這些表格數據往往格式不一&#xff0c;但有一個共同的需求&#xff1a; 從中提取出“字段-值”結構&#xff0c;統一導入 Excel&#xff0c;方便后續分析處理。 傳統手工操作…

github代碼中遇到的問題-解決方案

下面內容介紹的是我個人在復現github代碼遇到的一些問題&#xff0c;如果也可以幫到你&#xff0c;請點個關注吧~ 1.我的項目位置在D盤&#xff0c;但是為什么下面終端的位置在E盤 -》cd /d D:\Users\xxxx&#xff08;后面的xxxx是你具體的文檔位置&#xff09; 2.怎么知道我…

使用Visual Studio 2022創建CUDA編程項目

要在 Visual Studio 2022 中開發 CUDA 程序,需要進行環境配置并了解基本開發流程。以下是詳細步驟: 環境準備 安裝 Visual Studio 2022 下載并安裝 Visual Studio 2022(社區版或專業版均可)。安裝時勾選 “使用 C++ 的桌面開發” 工作負載。確保安裝 “C++ CMake 工具” …

Java測試題一

1.基本數據類型有哪些&#xff1f; 基本數據類型有8個&#xff1a;整數&#xff1a;byte、int、long、short。 浮點型&#xff1a;float、double。 布爾型boolean。 字符型&#xff1a;char 2.下列代碼的輸出是什么&#xff1f;為什么&#xff1f; public static void ma…

使用 Flask 構建基于 Dify 的企業資金投向與客戶分類評估系統

使用 Flask 構建基于 Dify 的企業資金投向與客戶分類評估系統 前言一、&#x1f9e9; 技術棧二、&#x1f4e6; 項目結構概覽三、 &#x1f527; 核心功能模塊說明1 配置參數2 請求封裝函數? 功能說明&#xff1a; 3 Prompt 構造函數4 Flask 路由定義&#x1f3e0; 首頁路由 /…

深入解析 AAC AudioSpecificConfig 在 RTSP/RTMP 播放器中的核心作用

在音視頻開發中&#xff0c;“能播”往往只是第一步&#xff0c;**“能正確、穩定、高質量地播”**才是衡量一款播放器成熟度的真正標準。尤其是在面對 AAC 音頻流時&#xff0c;很多開發者容易忽視一個極其關鍵但看似微小的配置段 —— AAC Audio Specific Config&#xff08;…

Redis在項目中的使用

Redis&#xff08;Remote Dictionary Server&#xff0c;遠程字典服務&#xff09;是一個開源的鍵值存儲系統&#xff0c;通常用作數據庫、緩存或消息傳遞系統。在項目中&#xff0c;Redis 可以發揮多種作用&#xff0c;以下是一些常見的使用場景&#xff1a; 1. 緩存 減少數據…