惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
爱范儿
爱范儿
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
博客园 - 聂微东
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
T
Tailwind CSS Blog
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
罗磊的独立博客
Jina AI
Jina AI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How to Compress PDF Files in the Browser (No Server Uploads)
sunshey · 2026-05-31 · via DEV Community

sunshey

 PDFs have a tendency to balloon in size. A resume with a few high-res images easily hits 20MB. A scanned contract? 50MB+. When you need to email a file or upload it to a form, size limits become a real problem.

Most online PDF tools solve this by uploading your file to their server, compressing it, and sending it back. It's convenient, but it means your sensitive documents — contracts, resumes, financial records — leave your device and land on someone else's cloud.

In this post, I'll show you how to compress PDFs without ever uploading them to a server, including a browser-based approach I built for exactly this problem.


Method 1: Built-in OS Tools (Quick but Limited)

Windows

Right-click PDF → Print → Select "Microsoft Print to PDF" → Save.

This creates a compressed version, but you have zero control over the compression level. Sometimes it works; sometimes it over-compresses and blurs text.

Mac

Open in Preview → File → Export → Quartz Filter → "Reduce File Size".

Same limitation — no quality control.

Best for: Quick one-off compression when quality isn't critical.


Method 2: Browser-Based Processing (Privacy-First)

This is the approach I use for sensitive documents. Instead of uploading to a server, the PDF opens directly in your browser and gets processed locally with JavaScript.

How It Works Under the Hood

At the core is pdf-lib, a powerful PDF manipulation library that runs entirely in the browser:

import { PDFDocument } from 'pdf-lib';

async function compressPDF(file) {
  const arrayBuffer = await file.arrayBuffer();
  const pdfDoc = await PDFDocument.load(arrayBuffer);

  // pdf-lib doesn't have a direct "compress" flag,
  // but you can optimize by re-saving with reduced quality
  const pdfBytes = await pdfDoc.save({ useObjectStreams: true });

  return new Blob([pdfBytes], { type: 'application/pdf' });
}

For image-heavy PDFs, the real compression happens at the image level. Here's how I handle it in sotool.top:

// Extract images, compress them, re-embed
const pages = pdfDoc.getPages();
for (const page of pages) {
  const images = await page.embeddedResources();
  for (const image of images) {
    if (image instanceof PDFImage) {
      // Reduce image quality based on user-selected compression level
      const compressed = await compressImage(image, quality);
      // Re-embed compressed image
    }
  }
}

Key advantage: Your file never leaves your computer. The server never sees the content.

Trade-off: Browser memory limits. A 500MB scanned document might crash the tab, whereas a server-based tool could handle it.

For typical documents under 100MB, the speed difference is negligible.


A Real-World Test

I tested three approaches on a 15MB scanned contract:

Method Output Size Quality Upload Required?
Windows Print to PDF 4.2MB Slightly blurred
Browser-based (sotool.top) 3.1MB Text crisp
Adobe Acrobat Pro 2.8MB Best
PDF24 (server-based) 3.0MB Good

The browser-based approach matched the server-based tool in quality, without the privacy trade-off.


When to Use What

File Type Recommended Tool Why
Sensitive docs (contracts, resumes, financial) Browser-based Files never leave your device
Large files (300MB+ scans) Desktop software Browser memory limits
Non-sensitive batches Server-based free tools Faster for bulk operations
Quick fixes Built-in OS tools Fastest, no setup

Performance Considerations

Compressing PDFs in the browser has unique constraints:

Memory: Chrome caps each tab at ~1-2GB. For very large files, stream pages one at a time instead of loading the entire document:

// Instead of loading the full file
const pdfDoc = await PDFDocument.load(arrayBuffer); // Loads everything

// Process pages incrementally
const pdfDoc = await PDFDocument.load(arrayBuffer, {
  updateMetadata: false
});
// Only access pages you need

CPU: Image compression is CPU-intensive. For batch processing, use requestIdleCallback to avoid blocking the UI:

function processBatch(files) {
  files.forEach((file, index) => {
    requestIdleCallback(() => {
      compressPDF(file).then(updateProgressBar);
    });
  });
}

Web Workers: For heavy lifting, offload to a Web Worker so the main thread stays responsive:

// worker.js
import { PDFDocument } from 'pdf-lib';

self.onmessage = async (e) => {
  const { file } = e.data;
  const compressed = await compressPDF(file);
  self.postMessage({ compressed });
};


The Bottom Line

For sensitive documents, browser-based PDF compression is the sweet spot between convenience and privacy. Modern JavaScript libraries like pdf-lib make it entirely feasible, and the performance gap with server-based tools is shrinking fast.

If you want to try a browser-based tool without signing up:

👉 en.sotool.top/compress

Free, no signup, files never leave your browser.


What's your approach to handling large PDFs? Do you prioritize convenience or privacy? Let me know in the comments.