使用JavaScript下載圖片并保存到本地超詳細實例代碼
更新時間:2025年05月13日 09:43:18 作者:Э時間行者于我
在JavaScript(JS)中,圖片下載通常涉及到前端與后端的交互,下面這篇文章主要介紹了使用JavaScript下載圖片并保存到本地的相關資料,文中通過代碼及圖文介紹的非常詳細,需要的朋友可以參考下
將選中的圖片下載到本地
1.先獲取到圖片信息
2.設置圖片信息
3.圖片下載實現(xiàn)原理解釋
- 首先,創(chuàng)建一個新的 Image 對象,并將圖片的 URL 賦值給它。
- 通過設置 crossOrigin 屬性為 “Anonymous”,解決跨域訪問的問題。
- 當圖片加載完成后,創(chuàng)建一個新的 canvas 元素,并將圖片繪制到 canvas 上。
- 創(chuàng)建一個新的 a元素作為下載鏈接,并設置下載的文件名為 imgName ,
a.download = filename || url.split('/').pop() || 'downloaded_image.jpg'
。 - 將 canvas 的數(shù)據(jù)轉換為 Data URL,并將其賦值給下載鏈接的 href 屬性。
- 最后,模擬用戶點擊下載鏈接,觸發(fā)圖片下載的操作。
js代碼
async function downloadImage(url, filename) { try { // 創(chuàng)建img元素 const img = new Image(); img.crossOrigin = 'Anonymous'; // 設置跨域 // 加載圖片 await new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; img.src = url + '?t=' + Date.now(); // 添加時間戳防止緩存 }); // 創(chuàng)建canvas并繪制圖片 const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); // 轉換為Blob并下載 canvas.toBlob(blob => { const blobUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = blobUrl; a.download = filename || url.split('/').pop() || 'downloaded_image.jpg'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(blobUrl); }, 'image/jpeg'); } catch (error) { console.error('下載失敗:', error); // alert('圖片下載失敗: ' + error.message); } } function downloadSelectedImages() { const selectedCheckboxes = document.querySelectorAll('.gallery-item input[type="checkbox"]:checked'); if (selectedCheckboxes.length === 0) { alert('請先選擇要下載的圖片'); return; } selectedCheckboxes.forEach(checkbox => { const img = checkbox.closest('.gallery-item').querySelector('img'); const imgUrl = img.src; const filename = imgUrl.split('/').pop() || 'downloaded_image.jpg'; downloadImage(imgUrl, filename); }); }
完整代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Image_Gallery圖片采集</title> <style> /* 全局樣式 */ * { padding: 0; margin: 0; } body { font-family: Arial, sans-serif; } .imgMain { width: 99%; min-height: 100%; border: 1px solid #ccc; margin: 10px; } /* 標題樣式 */ .header { font-size: 20px; font-weight: bold; padding: 10px 10px; border-bottom: 1px solid #ccc; } /* 副標題樣式 */ .sub-header { width: 95%; font-size: 18px; font-weight: bold; margin: 20px auto; display: flex; } .sub-header-space { width: 500px; height: 2px; margin-top: 11px; border-bottom: 1px solid #ccc; } .sub-header-item { color: #ccc; } .sub-header-item-selected { color: #333; } /* 圖片庫樣式 */ .gallery { display: flex; flex-wrap: wrap; align-content: flex-start; width: 95%; height: 680px; margin: 0 auto; gap: 5px; overflow: auto; } /*滾動條樣式*/ .gallery::-webkit-scrollbar { width: 8px; } .gallery::-webkit-scrollbar, .gallery::-webkit-scrollbar-thumb { border-radius: 10px; -webkit-box-shadow: inset 0 0 5px rgba(63, 136, 219, 0.5); background: rgba(10, 109, 238, 0.5); } .gallery::-webkit-scrollbar, .gallery::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5); border-radius: 0; background: rgba(0, 0, 0, 0.1); } .gallery-item { position: relative; width: 100px; height: 100px; margin: 5px; } .gallery-item img { width: 100%; height: 100%; object-fit: cover; cursor: pointer; border: 2px solid #2e8cf0; /* 添加默認邊框線 */ box-sizing: border-box; /* 確保邊框不占用額外空間 */ } .gallery-item img.selected { border-color: blue; /* 選中圖片的邊框顏色 */ } .gallery-item input[type="checkbox"] { position: absolute; top: 5px; left: 5px; z-index: 1; width: 26px; height: 26px; } /* 模態(tài)框樣式 */ .modal { display: none; position: fixed; z-index: 1; padding-top: 60px; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0, 0, 0, 0.9); } .modal-content { margin: auto; display: block; max-width: 80%; max-height: 80%; } .close { position: absolute; top: 20px; right: 35px; color: #fff; font-size: 40px; font-weight: bold; transition: 0.3s; cursor: pointer; } .close:hover { color: #bbb; } .nextButtonBox { width: 100%; margin-top: 20px; border-top: 1px solid #ccc; height: 74px; position: relative; left: 0; } /* 下一步按鈕樣式 */ .next-button { margin-top: 20px; padding: 10px 20px; background-color: #2d8cf0; color: white; border: none; cursor: pointer; position: absolute; right: 20px; } .next-button:disabled { background-color: #ccc; cursor: not-allowed; } /* 新增刪除按鈕樣式 */ .delete-btn { position: absolute; top: 2px; right: 2px; width: 20px; height: 20px; background: rgba(255, 0, 0, 0.8); border-radius: 50%; color: white; text-align: center; line-height: 20px; cursor: pointer; display: none; z-index: 2; } .delete-btn::after { content: "×"; font-size: 18px; } .gallery-item:hover .delete-btn { display: block; } /* 步驟容器 */ .step-container { display: none; padding: 10px; } .step-container.active { display: block; } /*滾動條樣式*/ .info-table::-webkit-scrollbar { width: 8px; } .info-table::-webkit-scrollbar, .info-table::-webkit-scrollbar-thumb { border-radius: 10px; -webkit-box-shadow: inset 0 0 5px rgba(63, 136, 219, 0.5); background: rgba(10, 109, 238, 0.5); } .info-table::-webkit-scrollbar, .info-table::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5); border-radius: 0; background: rgba(0, 0, 0, 0.1); } /* 表格樣式 */ .info-table { width: 100%; border-collapse: collapse; margin: 20px 0; } /* 設置表頭為塊級元素,以便與tbody對齊 */ .info-table thead, tbody tr { display: table; width: 100%; table-layout: fixed; } /* 設置tbody為塊級元素,并限制高度 */ .info-table tbody { display: block; min-height: 500px; max-height: 580px; /* 設置最大高度 */ overflow-y: auto; /* 當內容超過高度時顯示垂直滾動條 */ } /* 設置表頭的樣式 */ .info-table thead { width: calc(100% - 1em); /* 減去滾動條的寬度 */ } .info-table tbody td select { width: 180px; } .info-table th, .info-table td { border: 1px solid #ddd; padding: 8px; text-align: left; } .info-table th { background-color: #f2f2f2; text-align: center; } .info-table input { width: 100%; padding: 5px; box-sizing: border-box; } .info-table tbody tr { min-height: 50px; } /* 操作按鈕 */ .action-buttons { display: flex; gap: 10px; position: relative; left: 0; min-width: 700px; } .error-msg { display: none; color: #515a6e; margin-top: 10px; position: absolute; padding: 10px; border-radius: 6px; top: 0; left: 50%; width: 800px; text-align: center; margin-left: -400px; background: #fff; /* border: 1px solid #ccc; */ } .msg-success { border: 1px solid #8ce6b0; background-color: #edfff3; } .msg-error { border: 1px solid #ffb08f; background-color: #ffefe6; } /* 表頭設置樣式 */ .header-setting { /* display: flex; */ align-items: center; gap: 5px; } .header-setting input { width: 150px; } .header-setting button { padding: 5px 10px; background-color: #2d8cf0; color: white; border: none; cursor: pointer; } a { text-decoration: none; color: #444; transition: all .3s; } div, img, ul, li, em, p, span { margin: 0; padding: 0; } ul, li { list-style: none; } em, p, span, i { font-style: normal; } input, select, textarea, button { margin: 0; padding: 0; font-size: 14px; font-family: 'Source Han Sans SC', 'PingFang SC', 'Microsoft YaHei', Helvetica, Arial, sans-serif; } /*分頁*/ .mo-pagination { min-width: 800px; display: block; overflow: hidden; } .mo-pagination-btn { float: left; height: 30px; line-height: 28px; box-sizing: border-box; border: 1px solid #ddd; background: #fff; padding: 0 10px; margin: 0 5px 5px 0; display: block; overflow: hidden; cursor: pointer; transition: all .3s; border-radius: 6px; } .mo-pagination-btn:hover { color: #068EFF; border-color: #068EFF; } .mo-pagination-disabled { pointer-events: none; opacity: .5; cursor: not-allowed; } .mo-pagination-select { float: left; display: block; overflow: hidden; line-height: 30px; margin: 0 5px 5px 0; } .mo-pagination-select em { float: left; } .mo-pagination-select select { float: left; height: 30px; line-height: 28px; border: 1px solid #ddd; background: #fff; padding: 0 10px; margin: 0 5px; display: block; overflow: hidden; transition: all .3s; border-radius: 6px; } .mo-pagination-select select:hover { border-color: #068EFF; } .mo-pagination-mark { float: left; height: 30px; line-height: 30px; padding: 0 10px; margin: 0 5px 5px 0; display: block; overflow: hidden; } .mo-pagination-num { float: left; display: block; overflow: hidden; margin: 0 5px 5px 0; } .mo-pagination-num a { float: left; width: 30px; text-align: center; height: 30px; line-height: 28px; box-sizing: border-box; border: 1px solid #ddd; margin: 0 3px; display: block; overflow: hidden; cursor: pointer; border-radius: 50%; } .mo-pagination-num a.active { color: #068EFF; border-color: #068EFF; } .mo-pagination-enter { float: left; display: block; overflow: hidden; line-height: 30px; } .mo-pagination-enter em { float: left; } .mo-pagination-enter input { width: 50px; height: 30px; text-align: center; line-height: 28px; box-sizing: border-box; border: 1px solid #ddd; background: #fff; float: left; margin: 0 5px; transition: all .3s; border-radius: 6px; } .mo-pagination-enter input:hover { color: #068EFF; border-color: #068EFF; } .stepButtonBox { width: 100%; margin-top: 20px; border-top: 1px solid #ccc; height: 74px; position: relative; left: 0; } /* 下一步按鈕樣式 */ .step-button { margin-top: 20px; padding: 10px 20px; background-color: #2d8cf0; color: white; border: none; cursor: pointer; position: absolute; right: 20px; } </style> </head> <body> <div class="imgMain"> <!-- 步驟1:選擇圖片 --> <div id="step1" class="step-container active"> <!-- 原有圖片選擇界面 --> <!-- 標題 --> <div class="header">圖片采集 <span style="color: #2d8cf0;">/ 添加至侵權圖庫</span></div> <!-- 副標題:選擇需保留的圖片 --> <div class="sub-header"> <div class="sub-header-item sub-header-item-selected"> 1.選擇需保留的圖片 </div> <div class="sub-header-space"></div> <div class="sub-header-item"> 2.填寫圖片信息 </div> </div> <!-- 圖片庫 --> <div class="gallery" id="gallery"> <!-- Images will be dynamically inserted here --> </div> <!-- 模態(tài)框 --> <div id="myModal" class="modal"> <span class="close">×</span> <img class="modal-content" id="img01"> </div> <!-- 下一步按鈕 --> <div class="nextButtonBox"> <button class="next-button" style="right: 210px;" onclick="downloadSelectedImages()">下載選中圖片</button> <button class="next-button" style="right: 120px;" onclick="toggleAll()">全選</button> <button id="nextButton" class="next-button" disabled>下一步</button> </div> </div> </div> <script src="https://code.jquery.com/jquery-3.0.0.min.js"></script> <script> const images = [ 'https://cbu01.alicdn.com/img/ibank/O1CN01qSXOXm1jPpTzR7GUs_!!2215737524541-0-cib.jpg_b.jpg', 'http://10.100.1.200:8888/public/2023-09/22-20-08-37-666/6EE713438-DG.jpg', 'http://10.100.1.200:8888/public/2019-06/06-20-20-51-764/7HH401674.jpg', 'http://10.100.1.200:8888/public/2023-09/20-11-13-45-329/6EE713378-R.jpg', 'http://10.100.1.200:8888/public/2023-11/16-17-22-54-092/1AG202989-E-S.jpg', 'http://10.100.1.200:8888/public/2023-04/14-18-03-29-123/6EE107530-R.jpg', 'http://10.100.1.200:8888/public/2022-09/19-14-12-31-471/8YY204605.jpg' ]; const gallery = document.getElementById('gallery'); const modal = document.getElementById('myModal'); const modalImg = document.getElementById('img01'); const nextButton = document.getElementById('nextButton'); // 下載選中圖片功能 // async function downloadImage(url, filename) { // try { // // 方案1:使用圖片代理(推薦) // const proxyUrl = `https://cors-anywhere.herokuapp.com/${url}`; // const response = await fetch(proxyUrl, { // headers: new Headers({ // 'Origin': window.location.origin, // 'Cache-Control': 'no-cache' // }) // }); // // const response = await fetch(url + '?t=' + Date.now(), { // 添加時間戳防止緩存 // // headers: new Headers({ // // 'Cache-Control': 'no-cache' // // }) // // }); // if (!response.ok && response.type !== 'opaque') { // throw new Error(`HTTP error! status: ${response.status}`); // } // const blob = await response.blob(); // const blobUrl = window.URL.createObjectURL(blob); // const a = document.createElement('a'); // a.href = blobUrl; // a.download = filename; // document.body.appendChild(a); // a.click(); // window.URL.revokeObjectURL(blobUrl); // document.body.removeChild(a); // } catch (error) { // console.error('下載失敗:', error); // // alert('部分圖片下載失敗,請檢查控制臺日志'); // } // } async function downloadImage(url, filename) { try { // 創(chuàng)建img元素 const img = new Image(); img.crossOrigin = 'Anonymous'; // 設置跨域 // 加載圖片 await new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; img.src = url + '?t=' + Date.now(); // 添加時間戳防止緩存 }); // 創(chuàng)建canvas并繪制圖片 const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); // 轉換為Blob并下載 canvas.toBlob(blob => { const blobUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = blobUrl; a.download = filename || url.split('/').pop() || 'downloaded_image.jpg'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(blobUrl); }, 'image/jpeg'); } catch (error) { console.error('下載失敗:', error); // alert('圖片下載失敗: ' + error.message); } } function downloadSelectedImages() { const selectedCheckboxes = document.querySelectorAll('.gallery-item input[type="checkbox"]:checked'); if (selectedCheckboxes.length === 0) { alert('請先選擇要下載的圖片'); return; } selectedCheckboxes.forEach(checkbox => { const img = checkbox.closest('.gallery-item').querySelector('img'); const imgUrl = img.src; const filename = imgUrl.split('/').pop() || 'downloaded_image.jpg'; downloadImage(imgUrl, filename); }); } let isAllSelected = false; // 全局狀態(tài)記錄全選狀態(tài) function toggleAll() { const checkboxes = document.querySelectorAll('.gallery-item input[type="checkbox"]'); isAllSelected = !isAllSelected; // 切換全選/反選狀態(tài) checkboxes.forEach(checkbox => { checkbox.checked = isAllSelected; }); updateNextButton(); // 更新下一步按鈕狀態(tài) updateButtonText(); // 更新按鈕文字 } function updateButtonText() { const btn = document.querySelector('.next-button[style*="right: 120px"]'); btn.textContent = isAllSelected ? '反選' : '全選'; } // 初始化數(shù)據(jù) var initialImages = [ // "http://10.100.1.200:8888/public/2024-08/15-18-57-39-747/13AC1304299.jpg", // "http://10.100.1.200:8888/public/2024-08/28-10-16-59-448/2SS322764.jpg" ]; // Function to update the next button state function updateNextButton() { const selectedImages = document.querySelectorAll('.gallery-item input[type="checkbox"]:checked'); nextButton.disabled = selectedImages.length === 0; } // Function to handle the next step function handleNextStep() { const selectedImages = document.querySelectorAll('.gallery-item input[type="checkbox"]:checked'); const selectedImageUrls = Array.from(selectedImages).map(checkbox => { return checkbox.closest('.gallery-item').querySelector('img').src; }); console.log("img", selectedImageUrls); initialImages = selectedImageUrls // alert('Selected Images: ' + selectedImageUrls.join(', ')); } // 修改圖片創(chuàng)建邏輯,增加刪除按鈕 function createGalleryItems() { images.forEach((src, index) => { const galleryItem = document.createElement('div'); galleryItem.className = `gallery-item Image_${index + 1}`; // 創(chuàng)建刪除按鈕 const deleteBtn = document.createElement('div'); deleteBtn.className = 'delete-btn'; // 刪除按鈕點擊事件 deleteBtn.addEventListener('click', function (e) { e.stopPropagation(); // 阻止事件冒泡 galleryItem.remove(); // 移除圖片項 updateNextButton(); // 更新按鈕狀態(tài) }); const img = document.createElement('img'); img.src = src; img.alt = `Image ${index + 1}`; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.addEventListener('change', updateNextButton); img.addEventListener('click', function () { // if (!checkbox.checked) { modal.style.display = 'block'; modalImg.src = this.src; // } }); galleryItem.appendChild(deleteBtn); // 添加刪除按鈕 galleryItem.appendChild(checkbox); galleryItem.appendChild(img); gallery.appendChild(galleryItem); }); } // Close modal when clicking the close button document.querySelector('.close').addEventListener('click', function () { modal.style.display = 'none'; }); // Handle next button click nextButton.addEventListener('click', handleNextStep); // 延遲兩秒鐘執(zhí)行圖片創(chuàng)建邏輯 document.addEventListener('DOMContentLoaded', () => { setTimeout(() => { createGalleryItems(); }, 1000); // 延遲兩秒鐘 }); // 全局數(shù)據(jù)存儲 let allData = []; let currentStep = 1; let currentPage = 1; let pageSize = 10; let totalImages = 0; // 步驟切換 function goToStep(step) { console.log('步驟切換', step); document.querySelectorAll('.step-container').forEach(el => { el.classList.remove('active'); }); document.getElementById(`step${step}`).classList.add('active'); // currentStep = step; if (step === 2) { initPagination(); generateTable(initialImages); } } function goBack() { goToStep(1); } // 初始化 document.addEventListener('DOMContentLoaded', () => { // 從第一步的下一步按鈕調用 document.getElementById('nextButton').addEventListener('click', () => { goToStep(2); }); }); </script> </body> </html>
總結
到此這篇關于使用JavaScript下載圖片并保存到本地的文章就介紹到這了,更多相關JS下載圖片并保存到本地內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
javascript使用shift+click實現(xiàn)選擇和反選checkbox的方法
這篇文章主要介紹了javascript使用shift+click實現(xiàn)選擇和反選checkbox的方法,涉及javascript針對鍵盤按鍵的判斷及checkbox的操作技巧,需要的朋友可以參考下2015-05-05JavaScript實現(xiàn)數(shù)字數(shù)組按照倒序排列的方法
這篇文章主要介紹了JavaScript實現(xiàn)數(shù)字數(shù)組按照倒序排列的方法,涉及javascript中sort方法的使用技巧,非常具有實用價值,需要的朋友可以參考下2015-04-04一文看懂如何簡單實現(xiàn)節(jié)流函數(shù)和防抖函數(shù)
這篇文章主要給大家介紹了如何通過一文看懂簡單實現(xiàn)節(jié)流函數(shù)和防抖函數(shù)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-09-09