做绿植o2o网站怎么样,加强网站政务服务建设方案,绍兴高端网站设计,手机音乐网站程序源码在日常办公和文件管理中#xff0c;PDF文件体积过大常常带来诸多困扰#xff1a;邮件附件发送受限、云端存储空间紧张、文档传输耗时过长。一个安全、高效且不泄露隐私的PDF压缩工具#xff0c;成为许多用户和开发者的刚需。 为此#xff0c;吾爱IIS#xff08;52IIS.COM…在日常办公和文件管理中PDF文件体积过大常常带来诸多困扰邮件附件发送受限、云端存储空间紧张、文档传输耗时过长。一个安全、高效且不泄露隐私的PDF压缩工具成为许多用户和开发者的刚需。为此吾爱IIS52IIS.COM推出了这款完全开源的PDF压缩工具。它采用先进的纯前端技术通过智能优化图片质量和移除冗余数据在保证可读性的前提下显著减小PDF文件体积。所有处理均在浏览器本地完成确保您的文档隐私零泄露。作为开源项目您可以在 GitHub 上查看其完整源代码。✨ 核心功能亮点智能压缩灵活可控多级压缩质量提供高质量较小压缩、中等质量推荐和低质量最大压缩三种预设满足不同场景需求。精细图片质量控制通过直观的滑块10%-100%可精确控制PDF中图片的压缩程度在文件大小和视觉效果间找到最佳平衡。批量处理高效便捷支持同时选择多个PDF文件进行压缩大幅提升处理效率。压缩完成后可单独下载每个文件或一键打包下载所有压缩后的文件。实时反馈清晰透明每个文件都显示原始大小、压缩后大小和压缩比例。压缩比例以颜色标识高绿、中黄、低灰直观呈现压缩效果。处理状态等待中、压缩中、完成、失败一目了然。隐私安全纯前端处理所有压缩操作均在您的浏览器本地完成PDF文件数据全程不会上传至任何服务器。基于pdf.js和pdf-lib两大专业库实现确保处理过程的准确性和可靠性。广泛兼容智能处理支持大部分标准PDF格式通过智能渲染和重编码技术实现有效压缩。注加密或损坏的PDF可能无法正常处理系统会给出明确提示。 完整Vue 3 TypeScript代码实现以下是该工具的核心代码实现基于Vue 3、TypeScript、Element Plus组件库并集成了pdf.js、pdf-lib、JSZip和FileSaver.js等专业库template div classflex flex-col flex-1 mt-3 DetailHeader :titleinfo.title/DetailHeader div classp-4 bg-white rounded-2xl div classmb-3 el-text typeinfo压缩PDF文档大小支持批量压缩所有操作在本地完成。/el-text /div div classmb-3 el-text typeinfo通过降低图片质量和移除冗余数据来减小PDF文件体积。/el-text /div div classmb-4 settings-section div classsettings-row div classsetting-item span classsetting-label压缩质量/span el-select v-modelcompressQuality stylewidth: 140px el-option label高质量 (较小压缩) valuehigh / el-option label中等质量 (推荐) valuemedium / el-option label低质量 (最大压缩) valuelow / /el-select /div div classsetting-item span classsetting-label图片质量/span el-slider v-modelimageQuality :min10 :max100 :format-tooltip(val: number) ${val}% stylewidth: 200px / /div /div /div div classmb-3 el-upload action accept.pdf :auto-uploadfalse :on-changeonFileChange :multipletrue :show-file-listfalse el-button typeprimary选择PDF文件/el-button /el-upload /div div v-iffiles.length classmt-3 div classmb-3 el-button typesuccess clickcompressAllFiles :disabledloading开始压缩/el-button el-button typewarning clickclearFiles :disabledloading清空文件/el-button /div div classfile-list div v-for(file, idx) in files :keyfile.uid classfile-item div classfile-info span classfile-name{{ file.name }}/span div classfile-sizes span classfile-size原始: {{ formatFileSize(file.size) }}/span span v-iffile.compressedSize classfile-size compressed 压缩后: {{ formatFileSize(file.compressedSize) }} /span span v-iffile.compressedSize classfile-ratio :classgetRatioClass(file) ({{ getRatio(file) }}) /span /div /div div classfile-actions el-button v-iffile.compressedUrl typeprimary sizesmall clickdownloadFile(file)下载/el-button el-button typedanger sizesmall clickremoveFile(idx)删除/el-button /div div v-iffile.status processing classfile-status el-icon classis-loadingLoading //el-icon span压缩中.../span /div div v-else-iffile.status done classfile-status done el-iconCircleCheck //el-icon span完成/span /div div v-else-iffile.status error classfile-status error el-iconCircleClose //el-icon span失败/span /div /div /div /div div v-ifloading classmt-3 el-alert typeinfo :titleloadingMsg show-icon :closablefalse / el-progress :percentageprogress :format() ${progress}% classmt-2 / /div div v-iferrorMsg classmt-3 el-alert typeerror :titleerrorMsg show-icon :closablefalse / /div div v-ifcompletedCount 0 classmt-3 el-alert typesuccess :title成功压缩 ${completedCount} 个文件 show-icon :closablefalse / div classmt-3 el-button typeprimary clickdownloadAllFiles全部下载/el-button /div /div /div ToolDetail title使用说明 el-text ul li点击选择PDF文件按钮选择一个或多个需要压缩的PDF文件。/li li选择压缩质量高质量保留更多细节低质量压缩比更大。/li li调整图片质量滑块控制PDF中图片的压缩程度。/li li点击开始压缩按钮开始压缩过程。/li li压缩完成后可以单独下载每个文件或批量下载所有文件。/li li所有压缩操作均在本地完成不会上传到服务器。/li li支持大部分标准PDF格式加密或损坏的PDF可能无法正常压缩。/li /ul /el-text /ToolDetail /div /template script setup langts import { ref, reactive, computed } from vue; import DetailHeader from /components/Layout/DetailHeader/DetailHeader.vue; import ToolDetail from /components/Layout/ToolDetail/ToolDetail.vue; import * as pdfjsLib from pdfjs-dist; import pdfjsWorker from pdfjs-dist/build/pdf.worker.min?url; import { PDFDocument } from pdf-lib; import { Loading, CircleCheck, CircleClose } from element-plus/icons-vue; import JSZip from jszip; import { saveAs } from file-saver; pdfjsLib.GlobalWorkerOptions.workerSrc pdfjsWorker; const info reactive({ title: PDF压缩工具, }); interface FileItem { uid: string; name: string; size: number; raw: File; status: pending | processing | done | error; compressedSize?: number; compressedUrl?: string; compressedBytes?: Uint8Array; } const files refFileItem[]([]); const loading ref(false); const loadingMsg ref(); const progress ref(0); const errorMsg ref(); const compressQuality ref(medium); const imageQuality ref(70); const completedCount computed(() files.value.filter(f f.status done).length); const onFileChange (file: any) { if (!file || !file.raw) return; if (file.raw.type ! application/pdf) { errorMsg.value 请选择PDF文件; return; } errorMsg.value ; const newFile: FileItem { uid: Date.now().toString() Math.random().toString(36).substr(2, 9), name: file.name, size: file.size, raw: file.raw, status: pending }; files.value.push(newFile); }; const formatFileSize (size: number): string { if (size 1024) return size B; if (size 1024 * 1024) return (size / 1024).toFixed(2) KB; return (size / (1024 * 1024)).toFixed(2) MB; }; const getRatio (file: FileItem): string { if (!file.compressedSize) return ; const ratio ((1 - file.compressedSize / file.size) * 100).toFixed(1); return ratio % 减少; }; const getRatioClass (file: FileItem): string { if (!file.compressedSize) return ; const ratio (1 - file.compressedSize / file.size) * 100; if (ratio 50) return ratio-high; if (ratio 20) return ratio-medium; return ratio-low; }; const removeFile (idx: number) { const file files.value[idx]; if (file.compressedUrl) { URL.revokeObjectURL(file.compressedUrl); } files.value.splice(idx, 1); }; const clearFiles () { files.value.forEach(file { if (file.compressedUrl) { URL.revokeObjectURL(file.compressedUrl); } }); files.value []; errorMsg.value ; }; const compressPDF async (file: FileItem): Promisevoid { const arrayBuffer await file.raw.arrayBuffer(); const pdfJsDoc await pdfjsLib.getDocument({ data: arrayBuffer.slice(0) }).promise; const numPages pdfJsDoc.numPages; const newPdfDoc await PDFDocument.create(); const quality imageQuality.value / 100; const scale getScaleByQuality(); for (let i 1; i numPages; i) { const page await pdfJsDoc.getPage(i); const viewport page.getViewport({ scale }); const canvas document.createElement(canvas); canvas.width viewport.width; canvas.height viewport.height; const context canvas.getContext(2d)!; context.fillStyle #FFFFFF; context.fillRect(0, 0, canvas.width, canvas.height); await page.render({ canvasContext: context, viewport, canvas, }).promise; const imgDataUrl canvas.toDataURL(image/jpeg, quality); const imgBytes await fetch(imgDataUrl).then(r r.arrayBuffer()); const img await newPdfDoc.embedJpg(imgBytes); const pdfPage newPdfDoc.addPage([viewport.width, viewport.height]); pdfPage.drawImage(img, { x: 0, y: 0, width: viewport.width, height: viewport.height, }); } const compressedBytes await newPdfDoc.save({ useObjectStreams: true, addDefaultPage: false, objectsPerTick: 50, }); const compressedSize compressedBytes.length; const blob new Blob([new Uint8Array(compressedBytes)], { type: application/pdf }); const compressedUrl URL.createObjectURL(blob); file.compressedSize compressedSize; file.compressedUrl compressedUrl; file.compressedBytes compressedBytes; }; const getScaleByQuality (): number { switch (compressQuality.value) { case high: return 1.5; case low: return 0.8; case medium: default: return 1.2; } }; const compressAllFiles async () { if (files.value.length 0) { errorMsg.value 请先选择PDF文件; return; } loading.value true; errorMsg.value ; progress.value 0; const pendingFiles files.value.filter(f f.status pending || f.status error); for (let i 0; i pendingFiles.length; i) { const file pendingFiles[i]; file.status processing; loadingMsg.value 正在压缩: ${file.name} (${i 1}/${pendingFiles.length}); try { await compressPDF(file); file.status done; } catch (err) { file.status error; console.error(压缩失败: ${file.name}, err); } progress.value Math.round(((i 1) / pendingFiles.length) * 100); } loading.value false; loadingMsg.value ; }; const downloadFile (file: FileItem) { if (!file.compressedUrl) return; const link document.createElement(a); link.href file.compressedUrl; const baseName file.name.replace(.pdf, ); link.download ${baseName}_compressed.pdf; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const downloadAllFiles async () { const completedFiles files.value.filter(f f.status done f.compressedBytes); if (completedFiles.length 0) { errorMsg.value 没有可下载的文件; return; } if (completedFiles.length 1) { downloadFile(completedFiles[0]); return; } loading.value true; loadingMsg.value 正在打包文件...; try { const zip new JSZip(); completedFiles.forEach(file { const baseName file.name.replace(.pdf, ); zip.file(${baseName}_compressed.pdf, file.compressedBytes!); }); const blob await zip.generateAsync({ type: blob }); saveAs(blob, compressed_pdfs.zip); } catch (err) { errorMsg.value 打包下载失败; console.error(err); } finally { loading.value false; loadingMsg.value ; } }; /script style scoped .settings-section { padding: 16px; background: #f8f9fa; border-radius: 8px; } .settings-row { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; } .setting-item { display: flex; align-items: center; gap: 8px; } .setting-label { font-size: 14px; color: #606266; white-space: nowrap; } .file-list { margin-top: 18px; border: 1px solid #e4e7ed; border-radius: 8px; overflow: hidden; } .file-item { display: flex; justify-content: space-between; align-items: center; padding: 12px 18px; border-bottom: 1px solid #e4e7ed; background: #fafbfc; transition: background-color 0.2s; flex-wrap: wrap; gap: 12px; } .file-item:hover { background: #f0f9ff; } .file-item:last-child { border-bottom: none; } .file-info { flex: 1; min-width: 200px; } .file-name { font-weight: 500; margin-right: 18px; } .file-sizes { display: flex; gap: 12px; margin-top: 4px; } .file-size { color: #666; font-size: 14px; } .file-size.compressed { color: #67c23a; font-weight: 500; } .file-ratio { font-size: 14px; font-weight: 500; } .ratio-high { color: #67c23a; } .ratio-medium { color: #e6a23c; } .ratio-low { color: #909399; } .file-actions { display: flex; gap: 8px; } .file-status { display: flex; align-items: center; gap: 6px; font-size: 14px; } .file-status.done { color: #67c23a; } .file-status.error { color: #f56c6c; } .file-status .is-loading { animation: rotate 1s linear infinite; } keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } ul { padding-left: 20px; margin: 0; line-height: 1.7; } .mt-2 { margin-top: 8px; } .mb-4 { margin-bottom: 16px; } /style 压缩效果对比压缩质量图片质量滑块适用场景预期压缩比高质量80%-100%存档、打印、重要文档20%-40%中等质量50%-70%日常办公、邮件发送40%-60%低质量10%-40%预览、快速传输60%-80% 典型使用场景邮件附件优化将超过邮箱附件限制的PDF文件压缩到允许范围内便捷发送。文档存储节省空间批量压缩合同、报告等文档节省云端或本地存储空间。网站上传速度提升压缩需要在网站上上传的PDF文件加快上传和加载速度。移动设备阅读优化减小PDF体积使其在手机、平板上更流畅地打开和浏览。 如何使用三步完成压缩上传文件点击“选择PDF文件”按钮可批量选择多个需要压缩的PDF文件。设置参数选择压缩质量预设高/中/低调整图片质量滑块10%-100%开始压缩点击“开始压缩”按钮等待处理完成。压缩后可单独下载或批量打包下载。 总结这款开源、纯前端的PDF压缩工具通过智能的图像优化和冗余数据移除技术在保证文档可读性的前提下显著减小文件体积。它完美继承了「52IIS工具箱」对用户隐私的严格保护理念所有处理均在本地完成让您可以放心地压缩任何敏感文档。无论您是需要频繁处理大型PDF的职场人士还是希望优化网站加载速度的开发者这款工具都能为您提供高效、安全、可控的压缩体验。欢迎访问 吾爱IIS工具页 免费使用也欢迎前往其 GitHub仓库 了解更多技术细节或参与贡献。