base64与图片的转换和预览(高阶玩法)
1.完整的功能描述
功能概述
这是一个网页工具,支持用户输入不同格式的图片数据或上传本地图片文件,对图片进行预览、转换为多种格式,并支持导出不同格式的图片数据。
输入方式
1. 文本输入 :用户可以输入 Data URL、公网图片 URL、Blob URL 或 Hex 字符串。支持的格式包括 data:image/...;base64 、 http(s)://xxx.jpg 、 blob:... 以及纯 Hex 字符串。
2. 文件上传 :用户也能选择上传本地图片文件,支持常见的图片格式。 核心功能
1. 预览功能 :用户点击“预览”按钮后,工具会根据输入内容尝试加载并显示图片。如果输入是网络图片,会处理 CORS 问题;若输入为 Hex 字符串,会将其转换为图片。
2. 转换功能 :点击“转换”按钮,工具会将输入的图片数据转换为 Data URL、Blob 对象信息、ArrayBuffer(十进制字节数组)和 Hex 字符串,并显示在对应的文本框中。
3. 导出功能 :
- 图片导出 :用户可以选择导出图片的格式(PNG、JPEG、WebP、GIF),点击“导出图片”按钮即可保存图片。
- 数据导出 :支持导出 Data URL、Blob 对象信息、ArrayBuffer 和 Hex 字符串,点击对应按钮可保存相应数据。 错误处理
当输入格式不支持、图片加载失败或转换出错时,工具会显示错误信息提示用户。同时,在加载过程中会显示加载状态,提升用户体验。
2.完整样式展示
3.完整代码演示
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>图片 ↔ 多格式预览、转换 & 导出</title><style>:root {--primary: #5c6bc0;--light: #f5f5f5;--dark: #424242;--accent: #ff7043;--radius: 8px;--button-hover: #ff7043;}* { box-sizing: border-box; margin: 0; padding: 0; }body {font-family: "Helvetica Neue", Arial, sans-serif;background-color: var(--light);color: var(--dark);display: flex;justify-content: center;padding: 40px 0;}.container {width: 90%;max-width: 800px;background-color: #fff;border-radius: var(--radius);box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);padding: 24px;}h1 {margin-bottom: 24px;text-align: center;color: var(--primary);}.note {color: #e53935;font-size: 0.9rem;margin-bottom: 16px;}.section {margin-bottom: 24px;}.section label {display: block;margin-bottom: 8px;font-weight: bold;}textarea, select, input[type="text"] {width: 100%;padding: 10px;border: 1px solid #ccc;border-radius: var(--radius);font-family: monospace;background: #fafafa;resize: vertical;}input[type="file"] {display: block;margin-top: 4px;}.buttons, .export-section {text-align: center;margin-top: 8px;}.buttons button, .export-btn {background: var(--primary);color: #fff;border: none;padding: 6px 12px;border-radius: var(--radius);cursor: pointer;font-size: 0.9rem;transition: background 0.3s;margin: 4px;}.buttons button:hover, .export-btn:hover {background: var(--button-hover);}#preview {display: block;max-width: 100%;border-radius: var(--radius);margin: 12px auto;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);}textarea[readonly] {background: #eee;}.field-with-btn {position: relative;}.field-with-btn textarea {margin-bottom: 8px;}.field-with-btn .export-btn {position: absolute;top: 8px;right: 8px;}.format-select-wrapper {display: flex;justify-content: space-between;align-items: center;gap: 8px;}.format-select-wrapper select {width: auto;}.error-message {color: #e53935;font-size: 0.9rem;margin-top: 8px;display: none;}.loading {position: relative;min-height: 100px;}.loading::after {content: "🔄 加载中...";display: block;text-align: center;color: var(--primary);padding: 20px;}</style>
</head>
<body>
<div class="container"><img src="data:image/png;base64,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" alt="Logo"><h1>图片 ↔ 多格式预览、转换 & 导出</h1><div class="note">⚠️ 请确保输入的是<b>图片文件的 URL</b>(例如 .jpg/.png/.webp 等),否则无法预览或转换。<br>⚠️ 注意:网络图片需要支持CORS才能正常加载</div><!-- Input and File Upload --><div class="section"><label for="textInput">输入 Data URL、公网图片 URL、Blob URL 或 Hex 字符串</label><textarea id="textInput" rows="3" placeholder="支持 data:image/...;base64, http(s)://xxx.jpg, blob:..., 纯 Hex"></textarea><div id="inputError" class="error-message"></div></div><div class="section"><label for="fileInput">或 上传 本地文件</label><input type="file" id="fileInput" accept="image/*"></div><div class="buttons"><button id="previewBtn">预览</button><button id="convertBtn">转换</button><button id="clearBtn" style="background:#999;">清空</button></div><!-- Image Preview --><div class="section loading" id="previewContainer"><label>图片预览</label><img id="preview" alt="预览图像" style="display:none;" crossorigin="anonymous"></div><!-- Format Selection and Export --><div class="section export-section"><label>导出预览图像</label><br><div class="format-select-wrapper"><select id="formatSelect"><option value="image/png">PNG</option><option value="image/jpeg">JPEG</option><option value="image/webp">WebP</option><option value="image/gif">GIF</option></select><button id="exportImageBtn" class="export-btn">导出图片</button></div></div><!-- Data URL Export --><div class="section field-with-btn"><label for="outDataUrl">Data URL(Base64)</label><textarea id="outDataUrl" rows="2" readonly></textarea><button class="export-btn" id="exportDataUrlBtn">导出 Data URL</button></div><!-- Blob Export --><div class="section field-with-btn"><label>Blob 对象 信息</label><textarea id="outBlob" rows="2" readonly placeholder="显示 Blob 的 size/type"></textarea><button class="export-btn" id="exportBlobInfoBtn">导出 Blob 信息</button></div><!-- ArrayBuffer Export --><div class="section field-with-btn"><label for="outArrayBuffer">ArrayBuffer(十进制字节数组)</label><textarea id="outArrayBuffer" rows="3" readonly></textarea><button class="export-btn" id="exportArrayBufferBtn">导出 ArrayBuffer</button></div><!-- Hex Export --><div class="section field-with-btn"><label for="outHex">Hex 字符串</label><textarea id="outHex" rows="3" readonly></textarea><button class="export-btn" id="exportHexBtn">导出 Hex</button></div>
</div><script>document.addEventListener('DOMContentLoaded', function() {// DOM元素引用const elements = {textInput: document.getElementById('textInput'),fileInput: document.getElementById('fileInput'),previewBtn: document.getElementById('previewBtn'),convertBtn: document.getElementById('convertBtn'),clearBtn: document.getElementById('clearBtn'),preview: document.getElementById('preview'),formatSelect: document.getElementById('formatSelect'),exportImageBtn: document.getElementById('exportImageBtn'),outDataUrl: document.getElementById('outDataUrl'),outBlob: document.getElementById('outBlob'),outArrayBuffer: document.getElementById('outArrayBuffer'),outHex: document.getElementById('outHex'),previewContainer: document.getElementById('previewContainer'),inputError: document.getElementById('inputError')};let currentBlob = null;let currentDataUrl = null;// 显示错误信息function showError(message) {elements.inputError.textContent = message;elements.inputError.style.display = 'block';elements.previewContainer.classList.remove('loading');}// 隐藏错误信息function hideError() {elements.inputError.style.display = 'none';}// 重置功能function resetAll() {elements.textInput.value = '';elements.fileInput.value = '';elements.preview.style.display = 'none';elements.outDataUrl.value = '';elements.outBlob.value = '';elements.outArrayBuffer.value = '';elements.outHex.value = '';currentBlob = null;currentDataUrl = null;hideError();elements.previewContainer.classList.remove('loading');if (elements.preview.src.startsWith('blob:')) {URL.revokeObjectURL(elements.preview.src);}}// 处理CORS代理请求async function fetchWithCORS(url) {try {const response = await fetch(url, {mode: 'cors',credentials: 'omit'});if (!response.ok) {throw new Error('无法加载图片');}return response;} catch (error) {throw new Error(`无法加载图片: ${error.message}`);}}// 预览功能async function previewInput() {try {elements.previewContainer.classList.add('loading');hideError();const input = elements.textInput.value.trim();const file = elements.fileInput.files[0];if (input) {if (/^data:image\//i.test(input)) { // Data URLcurrentDataUrl = input;const img = new Image();img.onload = async () => {elements.preview.src = currentDataUrl;elements.preview.style.display = 'block';elements.previewContainer.classList.remove('loading');// 调用转换功能以更新数据显示await convertInput();};img.onerror = () => {throw new Error('无效的Data URL图片');};img.src = currentDataUrl;} else if (/^https?:\/\//i.test(input)) { // 网络URLconst img = new Image();img.crossOrigin = "Anonymous";img.onload = async () => {elements.preview.src = input;elements.preview.style.display = 'block';elements.previewContainer.classList.remove('loading');// 调用转换功能以更新数据显示await convertInput();};img.onerror = async () => {try {const response = await fetchWithCORS(input);const blob = await response.blob();const url = URL.createObjectURL(blob);elements.preview.src = url;elements.preview.style.display = 'block';elements.previewContainer.classList.remove('loading');// 调用转换功能以更新数据显示await convertInput();} catch (error) {throw new Error('图片加载失败');}};img.src = input;} else if (/^blob:/i.test(input)) { // Blob URLelements.preview.src = input;elements.preview.style.display = 'block';elements.previewContainer.classList.remove('loading');// 调用转换功能以更新数据显示await convertInput();} else if (/^[0-9a-f\s]+$/i.test(input)) { // Hex字符串// 直接调用转换功能处理Hex字符串await convertInput();} else {throw new Error('不支持的输入格式');}} else if (file) { // 本地文件const url = URL.createObjectURL(file);elements.preview.src = url;elements.preview.style.display = 'block';elements.previewContainer.classList.remove('loading');// 调用转换功能以更新数据显示await convertInput();} else {throw new Error('请输入内容或上传文件');}} catch (error) {console.error('预览错误:', error);showError(`预览错误: ${error.message}`);elements.preview.style.display = 'none';elements.previewContainer.classList.remove('loading');}}// 转换功能async function convertInput() {try {elements.previewContainer.classList.add('loading');hideError();const input = elements.textInput.value.trim();const file = elements.fileInput.files[0];let blob, buffer;if (input) {if (/^data:image\//i.test(input)) { // Data URLcurrentDataUrl = input;blob = await fetch(currentDataUrl).then(r => r.blob());} else if (/^https?:\/\//i.test(input)) { // 网络URLconst response = await fetchWithCORS(input);blob = await response.blob();// 验证图片类型if (!blob.type.startsWith('image/')) {throw new Error('URL指向的不是图片文件');}} else if (/^blob:/i.test(input)) { // Blob URLconst response = await fetch(input);blob = await response.blob();} else if (/^[0-9a-f\s]+$/i.test(input)) { // Hex字符串let cleanHex = input.replace(/\s+/g, '');if (cleanHex.length % 2 !== 0) throw new Error('Hex长度无效');buffer = new Uint8Array(cleanHex.match(/../g).map(h => parseInt(h, 16)));blob = new Blob([buffer], { type: 'image/*' });} else {throw new Error('不支持的输入格式');}} else if (file) { // 本地文件blob = file;} else {throw new Error('请输入内容或上传文件');}if (!blob) {throw new Error('无法创建Blob对象');}// 更新数据展示currentBlob = blob;buffer = await blob.arrayBuffer();// 生成Data URLcurrentDataUrl = await blobToDataURL(blob);elements.preview.src = currentDataUrl;elements.preview.style.display = 'block';elements.outDataUrl.value = currentDataUrl;elements.outBlob.value = `size: ${blob.size} bytes\ntype: ${blob.type || '未知类型'}`;const uint8 = new Uint8Array(buffer);elements.outArrayBuffer.value = JSON.stringify([...uint8]);elements.outHex.value = [...uint8].map(b => b.toString(16).padStart(2, '0')).join('');elements.previewContainer.classList.remove('loading');} catch (error) {console.error('转换错误:', error);showError(`转换错误: ${error.message}`);elements.preview.style.display = 'none';elements.previewContainer.classList.remove('loading');}}// 工具函数:Blob转DataURLfunction blobToDataURL(blob) {return new Promise((resolve) => {const reader = new FileReader();reader.onloadend = () => resolve(reader.result);reader.readAsDataURL(blob);});}// 导出图片功能elements.exportImageBtn.addEventListener('click', async () => {if (!currentDataUrl) {showError('请先转换图片');return;}try {const img = new Image();img.crossOrigin = "Anonymous";img.src = currentDataUrl;await new Promise((resolve, reject) => {img.onload = resolve;img.onerror = () => reject(new Error('图片加载失败'));});const canvas = document.createElement('canvas');canvas.width = img.naturalWidth;canvas.height = img.naturalHeight;const ctx = canvas.getContext('2d');ctx.drawImage(img, 0, 0);const type = elements.formatSelect.value;canvas.toBlob(blob => {const url = URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = `image_export.${type.split('/')[1] || 'png'}`;a.click();setTimeout(() => {URL.revokeObjectURL(url);URL.revokeObjectURL(img.src);}, 1000);}, type, 0.9);} catch (error) {console.error('导出图片错误:', error);showError(`导出图片错误: ${error.message}`);}});// 通用导出处理function setupExportButton(buttonId, contentFieldId, filename) {const button = document.getElementById(buttonId);const contentField = document.getElementById(contentFieldId);button.addEventListener('click', () => {const content = contentField.value;if (!content) {showError('无可用数据');return;}const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });const url = URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = filename;a.click();setTimeout(() => URL.revokeObjectURL(url), 1000);});}// 绑定导出功能setupExportButton('exportDataUrlBtn', 'outDataUrl', 'dataurl.txt');setupExportButton('exportBlobInfoBtn', 'outBlob', 'blob_info.txt');setupExportButton('exportArrayBufferBtn', 'outArrayBuffer', 'arraybuffer.json');setupExportButton('exportHexBtn', 'outHex', 'hex.txt');// 事件监听elements.previewBtn.addEventListener('click', previewInput);elements.convertBtn.addEventListener('click', convertInput);elements.clearBtn.addEventListener('click', resetAll);elements.textInput.addEventListener('input', hideError);elements.fileInput.addEventListener('change', hideError);});
</script>
</body>
</html><style>:root {--primary: #5c6bc0;--light: #f5f5f5;--dark: #424242;--accent: #ff7043;--radius: 12px;--button-hover: #ff7043;--transition: all 0.3s ease;}* { box-sizing: border-box; margin: 0; padding: 0; }body {font-family: "Helvetica Neue", Arial, sans-serif;background-color: var(--light);color: var(--dark);display: flex;justify-content: center;align-items: center;min-height: 100vh;padding: 20px;}.container {width: 90%;max-width: 1000px;background-color: #fff;border-radius: var(--radius);box-shadow: 0 6px 30px rgba(0, 0, 0, 0.1);padding: 32px;transition: var(--transition);}.container:hover {box-shadow: 0 8px 40px rgba(0, 0, 0, 0.15);}h1 {margin-bottom: 32px;text-align: center;color: var(--primary);font-size: 2.2rem;}.note {color: #e53935;font-size: 1rem;margin-bottom: 24px;padding: 12px;background-color: #ffebee;border-radius: var(--radius);}.section {margin-bottom: 32px;padding: 16px;background-color: #fafafa;border-radius: var(--radius);transition: var(--transition);}.section:hover {background-color: #f5f5f5;}.section label {display: block;margin-bottom: 12px;font-weight: bold;color: var(--primary);}textarea, select, input[type="text"] {width: 100%;padding: 14px;border: 1px solid #ddd;border-radius: var(--radius);font-family: monospace;background: #fff;resize: vertical;transition: var(--transition);}textarea:focus, select:focus, input[type="text"]:focus {border-color: var(--primary);outline: none;box-shadow: 0 0 0 3px rgba(92, 107, 192, 0.2);}input[type="file"] {display: block;margin-top: 8px;padding: 8px 0;}.buttons, .export-section {text-align: center;margin-top: 16px;}.buttons button, .export-btn {background: var(--primary);color: #fff;border: none;padding: 10px 20px;border-radius: var(--radius);cursor: pointer;font-size: 1rem;transition: var(--transition);margin: 6px;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);}.buttons button:hover, .export-btn:hover {background: var(--button-hover);transform: translateY(-2px);box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);}#preview {display: block;max-width: 100%;border-radius: var(--radius);margin: 16px auto;box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);transition: var(--transition);}#preview:hover {transform: scale(1.02);}textarea[readonly] {background: #f8f8f8;color: #666;}.field-with-btn {position: relative;}.field-with-btn textarea {margin-bottom: 12px;}.field-with-btn .export-btn {position: absolute;top: 12px;right: 12px;padding: 6px 12px;font-size: 0.9rem;}.format-select-wrapper {display: flex;justify-content: space-between;align-items: center;gap: 12px;}.format-select-wrapper select {width: auto;min-width: 120px;}.error-message {color: #e53935;font-size: 1rem;margin-top: 12px;display: none;padding: 8px;background-color: #ffebee;border-radius: var(--radius);}.loading {position: relative;min-height: 150px;}.loading::after {content: "🔄 加载中...";display: block;text-align: center;color: var(--primary);padding: 30px;font-size: 1.2rem;}</style>