欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 压缩包网页预览(zip-html-preview)

压缩包网页预览(zip-html-preview)

2025/4/19 17:58:05 来源:https://blog.csdn.net/bingbingyihao/article/details/147315845  浏览:    关键词:压缩包网页预览(zip-html-preview)

zip-html-preview

项目介绍

这是一个基于 Spring Boot 开发的在线 ZIP 文件预览工具,主要用于预览 ZIP 压缩包中的 HTML 文件及其相关资源。

主要功能

  • 支持拖拽上传或点击选择多个 ZIP 文件
  • 自动解压并提取 ZIP 文件中的 HTML 文件
  • 在线预览 HTML 文件及其相关的 CSS、JavaScript 和图片等资源
  • 支持多文件批量处理

技术栈

  • 后端:Spring Boot 2.3.4
  • 前端:HTML5 + JavaScript
  • 构建工具:Maven

快速开始

环境要求

  • JDK 8+
  • Maven 3.x

配置说明

application.properties 中配置解压文件存储路径:

zip.extract.path=D:/unzip

运行步骤

  1. 克隆项目
git clone https://gitee.com/anxwefndu/zip-html-preview.git
  1. 进入项目目录
cd zip-html-preview/SpringBoot
  1. 编译打包
mvn clean package
  1. 运行项目
java -jar target/SpringBoot-1.0-SNAPSHOT-execute.jar
  1. 访问应用
    打开浏览器访问: http://localhost:8080

使用说明

  1. 打开网页后,可以通过拖拽或点击选择按钮上传 ZIP 文件
  2. 支持同时选择多个 ZIP 文件
  3. 上传完成后会自动显示可预览的 HTML 文件列表
  4. 点击文件名即可在新标签页中预览对应的 HTML 文件

源码下载

zip-html-preview

演示截图

1.系统首页
在这里插入图片描述

2.预览压缩包
在这里插入图片描述

3.预览页面1
在这里插入图片描述

4.预览页面2
在这里插入图片描述

核心源码

SpringBoot/src/main/resources/static/index.html

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>zip-html-preview</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet"><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"><script src="https://cdn.tailwindcss.com"></script><script>tailwind.config = {theme: {extend: {colors: {primary: '#4F46E5',secondary: '#6366F1'},borderRadius: {'none': '0px','sm': '2px',DEFAULT: '4px','md': '8px','lg': '12px','xl': '16px','2xl': '20px','3xl': '24px','full': '9999px','button': '4px'}}}}</script><style>body::-webkit-scrollbar {width: 0.5rem;}body::-webkit-scrollbar-track {background: #f1f1f1;border-radius: 0.5rem;}body::-webkit-scrollbar-thumb {background: #3498db;border-radius: 0.5rem;}body::-webkit-scrollbar-thumb:hover {background: #2980b9;}.drag-area {border: 2px dashed #E5E7EB;transition: all 0.3s ease;}.drag-area:hover {border-color: #4F46E5;}.file-input {display: none;}.button-hover {transition: transform 0.2s ease;}.button-hover:active {transform: translateY(2px);}</style></head><body class="bg-gray-50"><div class="w-[1200px] mx-auto"><nav class="h-16 bg-white shadow-sm flex items-center justify-between px-8"><div class="flex items-center space-x-2"><span class="text-2xl font-['Pacifico'] text-primary">logo</span><span class="text-lg font-medium">zip-html-preview</span></div><button class="w-10 h-10 rounded-button flex items-center justify-center hover:bg-gray-100 transition-colors"><i class="fas fa-sun text-gray-600"></i></button></nav><main class="px-8 py-12"><div class="max-w-3xl mx-auto"><div class="bg-white rounded-lg shadow-sm p-8"><div id="dropArea" class="drag-area rounded-lg p-12 text-center"><input type="file" id="fileInput" class="file-input" multiple accept=".zip"><div class="space-y-4"><div class="w-20 h-20 mx-auto bg-gray-50 rounded-full flex items-center justify-center"><i class="fas fa-cloud-upload-alt text-4xl text-gray-400"></i></div><div><h3 class="text-lg font-medium">拖拽文件到这里,或</h3><button class="mt-2 px-6 py-2 bg-primary text-white rounded-button hover:bg-primary/90 button-hover whitespace-nowrap">点击选择文件</button></div><p class="text-sm text-gray-500">支持的文件格式:ZIP</p></div></div><div id="fileList" class="hidden mt-8 space-y-4"><div class="text-lg font-medium mb-4">已选择的文件</div><div class="space-y-3"></div><div class="flex justify-end space-x-3 mt-6"><button id="clearButton" class="px-6 py-2 text-gray-600 bg-gray-100 rounded-button hover:bg-gray-200 button-hover whitespace-nowrap">清空列表</button><button id="previewButton" class="px-6 py-2 text-white bg-primary rounded-button hover:bg-primary/90 button-hover whitespace-nowrap">预览</button></div></div><div id="previewLinks" class="hidden mt-8 space-y-4"><div class="text-lg font-medium mb-4">可预览的文件</div><ul class="space-y-2" id="htmlFilesList"></ul></div></div><div class="mt-12 bg-white rounded-lg shadow-sm p-8"><h2 class="text-xl font-medium mb-6">使用说明</h2><div class="space-y-4 text-gray-600"><div class="flex items-start space-x-3"><div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5"><i class="fas fa-check text-sm text-primary"></i></div><p>支持拖拽上传或点击选择文件,可以一次选择多个ZIP文件</p></div><div class="flex items-start space-x-3"><div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5"><i class="fas fa-check text-sm text-primary"></i></div><p>系统会自动解析ZIP文件中的HTML文件,并提供在线预览功能</p></div><div class="flex items-start space-x-3"><div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5"><i class="fas fa-check text-sm text-primary"></i></div><p>支持预览ZIP包中的HTML文件及其相关的CSS、JavaScript和图片等资源</p></div><div class="flex items-start space-x-3"><div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5"><i class="fas fa-check text-sm text-primary"></i></div><p>提供文件树视图,方便浏览ZIP包中的文件结构和快速切换不同的HTML文件</p></div></div></div></div></main></div><script>const dropArea = document.getElementById('dropArea');const fileInput = document.getElementById('fileInput');const fileList = document.getElementById('fileList');const previewButton = document.getElementById('previewButton');const clearButton = document.getElementById('clearButton');const previewLinks = document.getElementById('previewLinks');const htmlFilesList = document.getElementById('htmlFilesList');// 存储所有文件的数组let selectedFiles = [];// 点击拖拽区域触发文件选择dropArea.addEventListener('click', () => {fileInput.click();});// 拖拽进入时改变样式dropArea.addEventListener('dragover', (e) => {e.preventDefault();dropArea.classList.add('border-primary');});// 拖拽离开时恢复样式dropArea.addEventListener('dragleave', () => {dropArea.classList.remove('border-primary');});// 拖拽放下时处理文件dropArea.addEventListener('drop', (e) => {e.preventDefault();dropArea.classList.remove('border-primary');const files = e.dataTransfer.files;handleFiles(files);});// 文件输入框变化时处理文件fileInput.addEventListener('change', () => {const files = fileInput.files;handleFiles(files);fileInput.value = null;});// 处理文件并更新文件列表function handleFiles(files) {for (let i = 0; i < files.length; i++) {const file = files[i];if (!selectedFiles.some(f => f.name === file.name)) {selectedFiles.push(file);}}updateFileList();}// 更新文件列表 DOMfunction updateFileList() {if (selectedFiles.length > 0) {fileList.classList.remove('hidden');} else {fileList.classList.add('hidden');}const listContainer = fileList.querySelector('.space-y-3');listContainer.innerHTML = ''; // 清空旧的文件列表selectedFiles.forEach((file, index) => {const fileType = file.type || 'text/plain';const fileSize = formatFileSize(file.size);const listItem = document.createElement('div');listItem.className = 'flex items-center justify-between p-4 bg-gray-50 rounded-lg';// 左侧:文件图标和信息const leftSide = document.createElement('div');leftSide.className = 'flex items-center space-x-3';const icon = document.createElement('i');icon.className = getIconClass(fileType);icon.style.color = '#4F46E5'; // 设置颜色const fileInfo = document.createElement('div');fileInfo.innerHTML = `<div class="font-medium">${escapeHTML(file.name)}</div><div class="text-sm text-gray-500">${fileSize}</div>`;leftSide.appendChild(icon);leftSide.appendChild(fileInfo);// 右侧:操作按钮const rightSide = document.createElement('div');rightSide.className = 'flex items-center space-x-2';// 删除按钮const deleteButton = document.createElement('button');deleteButton.className = 'p-2 text-gray-400 hover:text-gray-600 rounded-button button-hover';deleteButton.innerHTML = '<i class="fas fa-times"></i>';deleteButton.addEventListener('click', () => removeFile(index));rightSide.appendChild(deleteButton);listItem.appendChild(leftSide);listItem.appendChild(rightSide);listContainer.appendChild(listItem);});}// 格式化文件大小function formatFileSize(size) {const units = ['B', 'KB', 'MB', 'GB'];let unitIndex = 0;while (size >= 1024 && unitIndex < units.length - 1) {size /= 1024;unitIndex++;}return `${size.toFixed(2)} ${units[unitIndex]}`;}// 获取文件类型的图标类名function getIconClass(type) {if (type.startsWith('image/')) {return 'fas fa-file-image text-primary w-8 h-8 flex items-center justify-center';} else if (type === 'text/plain' || type.endsWith('.md')) {return 'fas fa-file-alt text-primary w-8 h-8 flex items-center justify-center';} else {return 'fas fa-file text-primary w-8 h-8 flex items-center justify-center';}}// 移除指定索引的文件function removeFile(index) {selectedFiles.splice(index, 1);updateFileList();}// 清空所有文件document.querySelector('#fileList .px-6.py-2.text-gray-600').addEventListener('click', () => {selectedFiles = [];updateFileList();});// 转义 HTML 特殊字符function escapeHTML(str) {return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');}// 清空所有文件clearButton.addEventListener('click', () => {selectedFiles = [];updateFileList();previewLinks.classList.add('hidden');htmlFilesList.innerHTML = '';});// 预览按钮点击事件previewButton.addEventListener('click', () => {if (selectedFiles.length === 0) return;const formData = new FormData();selectedFiles.forEach(file => formData.append('file', file));fetch('/api/upload', {method: 'POST',body: formData}).then(response => response.json()).then(data => {previewLinks.classList.remove('hidden');htmlFilesList.innerHTML = '';data.forEach(htmlFile => {const listItem = document.createElement('li');listItem.className = 'flex items-center justify-between p-4 bg-gray-50 rounded-lg';const fileName = document.createElement('a');fileName.href = htmlFile.filePath;fileName.target = '_blank';fileName.className = 'text-blue-500 hover:underline';fileName.textContent = htmlFile.fileName;listItem.appendChild(fileName);htmlFilesList.appendChild(listItem);});}).catch(error => {alert('上传失败,请稍后再试。');console.error('Error:', error);});});</script></body></html>

SpringBoot/src/main/java/com/boot/service/ZipService.java

package com.boot.service;import com.boot.config.ZipConfig;
import com.boot.model.HtmlFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;@Service
public class ZipService {@Autowiredprivate ZipConfig zipConfig;public List<HtmlFile> processZipFile(MultipartFile file) throws IOException {String extractDir = zipConfig.getExtract().getPath();File dir = new File(extractDir);if (!dir.exists()) {dir.mkdirs();}// 解压文件try (ZipInputStream zis = new ZipInputStream(file.getInputStream(), Charset.forName("GBK"))) {ZipEntry zipEntry;byte[] buffer = new byte[1024];while ((zipEntry = zis.getNextEntry()) != null) {File newFile = new File(extractDir + File.separator + zipEntry.getName());if (zipEntry.isDirectory()) {newFile.mkdirs();continue;}// 创建父目录new File(newFile.getParent()).mkdirs();// 写入文件try (FileOutputStream fos = new FileOutputStream(newFile)) {int len;while ((len = zis.read(buffer)) > 0) {fos.write(buffer, 0, len);}}}}// 查找第一层的HTML文件List<HtmlFile> htmlFiles = new ArrayList<>();// 提取文件夹名称(去掉扩展名)String folderName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf('.'));extractDir = extractDir + File.separator + folderName;try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(extractDir))) {for (Path path : stream) {if (Files.isRegularFile(path) && path.toString().toLowerCase().endsWith(".html")) {htmlFiles.add(new HtmlFile(path.getFileName().toString(), "/preview" + path.toString().substring(zipConfig.getExtract().getPath().length())));}}}return htmlFiles;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词