freeCodeCamp.org

How to Build a Browser-Based PDF Blur Tool Using JavaScript

8.5内容质量
How to Build a Browser-Based PDF Blur Tool Using JavaScript

TL;DR · AI 摘要

本文提供基于JavaScript的PDF模糊工具开发方案,使用PDF.js和PDF-lib实现浏览器端PDF处理,无需服务器交互。

核心要点

  • 使用PDF.js渲染PDF页面并转换为HTML Canvas进行模糊操作
  • 通过PDF-lib库实现模糊效果的PDF文件生成
  • 支持区域选择、强度调节和多页处理的完整功能链

结构提纲

按章节快速跳转。

  1. 介绍PDF模糊工具在信息保护场景中的必要性及浏览器端实现优势。

  2. 说明PDF.js、HTML Canvas和PDF-lib在项目中的核心作用及协作方式。

  3. 分步骤解析从PDF上传到最终文件生成的完整技术实现路径。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 浏览器PDF模糊工具
    • 技术实现
      • PDF.js渲染
      • Canvas交互
      • PDF-lib生成
    • 功能模块
      • 区域选择
      • 强度调节
      • 多页处理

金句 / Highlights

值得收藏与分享的关键句。

#JavaScript#PDF处理#前端工具#浏览器开发
打开原文

如何使用 JavaScript 构建基于浏览器的 PDF 模糊工具

2026年7月24日

/

#JavaScript

Bhavin Sheth

许多 PDF 文档包含不应公开共享的信息。个人详细信息、财务数据、签名、地址、账户号码、员工信息或机密业务数据在发送文件给其他人之前通常需要隐藏。

PDF 模糊工具使这一过程变得简单。它不会永久删除内容,而是在 PDF 的选定区域上添加模糊效果,使敏感信息难以阅读,同时保持文档其余部分不变。

在本教程中,你将使用 JavaScript 构建一个基于浏览器的 PDF 模糊工具。用户将能够上传 PDF,预览每一页,在敏感内容上绘制模糊框,调整模糊强度,将模糊效果应用到选定页面,预览最终结果,并下载处理后的 PDF,整个过程无需将文件上传到服务器。

我们将使用 PDF.js 在浏览器中渲染 PDF 页面,使用 HTML Canvas 创建和管理模糊区域,并使用 PDF-lib 生成最终的模糊 PDF。

完成本教程后,你将拥有一个功能齐全的客户端 PDF 编辑工具,与我网站(AllInOneTools)上提供的工具类似。

目录

  • 这个 PDF 模糊工具的功能及其工作原理
  • 项目设置
  • 创建 HTML 布局
  • 上传和预览 PDF
  • 创建模糊区域
  • 将模糊效果应用到页面
  • 生成最终 PDF
  • 预览结果
  • 重命名和下载
  • 演示:PDF 模糊工具的工作原理
  • 性能优化技巧
  • 常见错误
  • 总结

这个 PDF 模糊工具的功能及其工作原理

PDF 模糊工具在文档共享前帮助保护敏感信息。它不会编辑或删除原始内容,而是在选定区域上应用视觉模糊效果,使机密信息变得不可读,同时保持文档其余部分不变。

这种方法对于隐藏个人详细信息、财务信息、账户号码、签名、地址、人脸或任何不应在最终文档中显示的私人内容非常有用。

在这个项目中,用户可以直接从浏览器上传 PDF,预览每一页,并在需要隐藏的区域绘制一个或多个模糊区域。该工具还允许用户调整模糊强度,对选定区域或整个页面进行模糊处理,将效果应用到当前页面、所有页面或特定页面范围,预览完成的文档,重命名输出文件,并下载最终的 PDF。

由于所有操作都在浏览器中运行,因此不会将文件上传到服务器,有助于保持文档隐私。

在后台,应用程序首先使用 PDF.js 将每一页 PDF 渲染到 HTML 画布上。而不是立即修改原始 PDF,它会记录用户创建的每个模糊区域的位置、大小、页码和模糊强度。

当用户点击“应用并最终确定”时,这些存储的区域会从浏览器坐标转换为实际的 PDF 页面坐标。然后将选定的模糊效果应用到渲染后的页面,PDF-lib 会生成一个包含模糊内容的新 PDF,同时保留文档的其余部分。

这种工作流程提供了交互式编辑体验,同时在最终生成文档之前保持原始 PDF 不变。

例如,每个模糊区域可以表示为如下对象:

code
const blurRegion = {

    page: 2,
code

    x: 180,

    y: 240,

    width: 260,

    height: 90,

    intensity: 6

};

每个对象都存储了在最终生成 PDF 过程中重现模糊效果所需的所有信息。

项目设置

在编写任何代码之前,让我们为 PDF Blur Tool 创建一个简单的项目结构。

我们将使用纯 HTML、CSS 和 JavaScript,以及两个库:

  • PDF.js 用于在浏览器中渲染 PDF 页面。
  • PDF-lib 用于生成最终的模糊 PDF。

我们的项目结构如下所示:

code
pdf-blur-tool/

│── index.html
│── style.css
│── script.js
│── pdf.worker.min.js
│── assets/

保持项目简单有助于更清楚地理解每个部分的工作原理。

在加载自己的 JavaScript 之前,先添加 PDF.js 和 PDF-lib。

code
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.4.168/pdf.min.js"></script>

<script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>

<script src="script.js"></script>

配置 PDF 工作线程。

code
pdfjsLib.GlobalWorkerOptions.workerSrc =
    "pdf.worker.min.js";

工作线程在后台线程中处理 PDF 渲染,有助于在页面渲染时保持界面的响应性。

创建 HTML 布局

该应用由四个主要部分组成:

  • 上传区域
  • PDF 预览
  • 模糊设置面板
  • 最终下载区域

创建基本布局:

code
<div id="uploadSection"></div>

<div id="editorSection" hidden>

    <div id="pdfPreview"></div>

    <aside id="blurSettings"></aside>

</div>

<div id="resultSection" hidden></div>

初始状态下,仅显示上传区域。

选择 PDF 后,编辑器将变得可见。

选择 DOM 元素

创建对应用中使用的元素的引用。

code
const uploadSection =
    document.getElementById(
        "uploadSection"
    );

const editorSection =
    document.getElementById(
        "editorSection"
    );

const resultSection =
    document.getElementById(
        "resultSection"
    );

const fileInput =
    document.getElementById(
        "pdfInput"
    );

const pdfCanvas =
    document.getElementById(
        "pdfCanvas"
    );

const canvasContext =
    pdfCanvas.getContext("2d");

这些引用使应用能够在上传、编辑和下载阶段之间切换。

上传和预览 PDF

上传区域支持拖放和传统文件选择两种方式。

当选择 PDF 后,在继续之前验证它确实是一个 PDF 文件。

code
async function handlePdfUpload(
    file
) {

    if (
        !file ||
        file.type !==
        "application/pdf"
    ) {

        alert(
            "Please select a PDF file."
        );

        return;

    }

    await loadPdf(file);

}

如果验证成功,文档将被加载到内存中。

读取 PDF

使用 File API 将上传的文件转换为 ArrayBuffer。

code
async function loadPdf(
    file
) {

    const bytes =
        await file.arrayBuffer();

    pdfDocument =
        await pdfjsLib
            .getDocument({
                data: bytes
            })
            .promise;

    currentPage = 1;

    await renderPage(
        currentPage
    );

}

上传的字节在生成模糊 PDF 时也会被再次使用。

渲染第一页

PDF.js 将每一页渲染到 HTML 画布上。

首先获取请求的页面。

code
async function renderPage(
    pageNumber
) {

const page =
        await pdfDocument
            .getPage(
                pageNumber
            );

    const viewport =
        page.getViewport({
            scale: 1.5
        });

调整画布大小以匹配页面尺寸。

code
pdfCanvas.width =
    viewport.width;

pdfCanvas.height =
    viewport.height;

渲染页面。

code
await page.render({

    canvasContext,

    viewport

}).promise;

渲染完成后,PDF 页面将在编辑器中显示出来。

创建页面导航

大多数 PDF 文档包含多页内容。

允许用户通过上一页和下一页按钮在页面间切换。

code
let currentPage = 1;

let pdfDocument = null;

切换到上一页。

code
previousButton
.addEventListener(
    "click",
    async () => {

        if (
            currentPage === 1
        ) {

            return;

        }

        currentPage--;

        await renderPage(
            currentPage
        );

    }
);

切换到下一页。

code
nextButton
.addEventListener(
    "click",
    async () => {

        if (
            currentPage ===
            pdfDocument.numPages
        ) {

            return;

        }

        currentPage++;

        await renderPage(
            currentPage
        );

    }
);

每当当前页面发生变化时更新页码显示。

code
pageIndicator.textContent =
    `Page ${currentPage} of ${pdfDocument.numPages}`;

这为用户在浏览大型 PDF 文档时提供了清晰的反馈。

准备模糊编辑

当前页面渲染完成后,应用程序会在 PDF 画布上方创建一个透明图层。

该图层用于捕获鼠标交互,而不会修改原始页面预览。

创建图层。

code
<canvas
    id="overlayCanvas">
</canvas>

调整其大小以匹配 PDF 预览。

code
overlayCanvas.width =
    pdfCanvas.width;

overlayCanvas.height =
    pdfCanvas.height;

在后续教程中,这个图层将允许用户在不修改底层 PDF 页面的情况下绘制模糊区域。

显示编辑器

当第一页渲染完成后,切换从上传界面到编辑器界面。

code
uploadSection.hidden =
    true;

editorSection.hidden =
    false;

用户现在可以预览文档、在页面间导航,并开始选择需要模糊的区域。

创建模糊区域

现在 PDF 预览功能已就绪,我们可以构建应用程序最重要的功能:允许用户对敏感信息进行模糊处理。

用户不会立即编辑 PDF,而是先在页面预览上绘制一个或多个模糊区域。

每个区域会存储自己的位置、尺寸和模糊强度。这些区域将在最终处理时转换为实际的 PDF 坐标。

创建模糊区域对象

每个模糊区域都表示为一个 JavaScript 对象。

例如:

code
const blurArea = {

    page: currentPage,

    x: 0,

    y: 0,

    width: 0,

    height: 0,

    intensity: 6

};

而不是立即修改 PDF,应用程序会简单地跟踪这些对象,直到用户点击“应用并最终处理”。

存储多个模糊区域

用户通常需要隐藏多处信息。

将所有模糊区域存储在一个数组中。

code
const blurAreas = [];

每当创建一个新的模糊框时,将其推入数组。

code
blurAreas.push({

    page: currentPage,

    x,

    y,

    width,

    height,

 /think

intensity: blurIntensity

});

code

这使得后续重新绘制、编辑或删除单个模糊区域变得简单。

### 开始模糊选择

透明叠加画布捕获鼠标交互。

当用户按下鼠标按钮时,记录起始位置。

let isDrawing = false;

let startX = 0;

let startY = 0;

overlayCanvas .addEventListener( "mousedown", event => {

isDrawing = true;

startX = event.offsetX;

startY = event.offsetY;

} );

code

模糊矩形从此处开始。

### 绘制模糊矩形

随着鼠标移动,更新矩形尺寸。

overlayCanvas .addEventListener( "mousemove", event => {

if ( !isDrawing ) {

return;

}

drawPreviewBox(

startX,

startY,

event.offsetX,

event.offsetY

);

} );

code

用户拖动鼠标时,预览会持续更新。

### 完成选择

当鼠标按钮释放时,保存完成的模糊区域。

overlayCanvas .addEventListener( "mouseup", event => {

isDrawing = false;

blurAreas.push({

page: currentPage,

x: startX,

y: startY,

width: event.offsetX - startX,

height: event.offsetY - startY,

intensity: blurIntensity

});

redrawBlurAreas();

updateBlurList();

} );

code

每个模糊区域都成为当前编辑会话的一部分。

### 绘制现有模糊区域

每当页面切换或添加模糊区域时,重新绘制所有模糊框。

function redrawBlurAreas() {

overlayContext.clearRect(

0,

0,

overlayCanvas.width,

overlayCanvas.height

);

blurAreas

.filter(

area =>

area.page === currentPage

)

.forEach(

drawBlurArea

);

}

code

这确保了在编辑过程中之前创建的模糊区域保持可见。

### 显示模糊框

使用虚线轮廓渲染每个存储的区域。

function drawBlurArea( area ) {

overlayContext .setLineDash([6, 4]);

overlayContext .strokeStyle = "#4f6cff";

overlayContext .strokeRect(

area.x,

area.y,

area.width,

area.height

);

}

code

轮廓作为参考线,不会成为最终PDF的一部分。

### 模糊选项

用户可以选择模糊的应用方式。

该工具支持两种模式:

- 模糊所选区域

- 模糊整个页面

所选选项控制编辑行为。

const blurMode = document.querySelector(

'input[name="blurMode"]:checked'

).value;

code

如果选择“模糊所选区域”,用户需要手动绘制模糊矩形。

如果选择“模糊整个页面”,应用会跳过手动选择,并在最终处理时准备模糊整个页面。

### 调整模糊强度

不同文档需要不同程度的模糊效果。

滑块让用户在应用效果前控制模糊强度。

const blurSlider = document.getElementById( "blurIntensity" );

let blurIntensity = 6;

code

blurSlider
.addEventListener(
    "input",
    event => {

        blurIntensity =
        Number(
            event.target.value
        );

    }
);

每次创建新的模糊区域时,所选值都会被存储。

code
blurArea.intensity =
blurIntensity;

数值越大,模糊效果越明显。

管理多个模糊区域

许多文档包含多个机密信息。

为了不限制用户仅使用一个模糊矩形,应用程序会显示所有已保存的区域。

code
模糊区域 #1

模糊区域 #2

模糊区域 #3

每个条目都包含一个删除按钮。

code
function removeBlurArea(
    index
) {

    blurAreas.splice(
        index,
        1
    );

    redrawBlurAreas();

    updateBlurList();

}

这使用户能够删除不再需要的模糊区域。

要从当前页面删除所有模糊区域:

code
function clearCurrentPage() {

    const remaining =

    blurAreas.filter(

        area =>

            area.page !==
            currentPage

    );

    blurAreas.length = 0;

    blurAreas.push(
        ...remaining
    );

    redrawBlurAreas();

}

对页面应用模糊效果

用户可能希望仅对文档中的某一页或几页应用模糊效果。

编辑器提供三种选项:

  • 仅当前页面
  • 所有页面
  • 指定页面
code
const pageOption =
document.querySelector(

'input[name="pageOption"]:checked'

).value;

如果用户选择"指定页面",他们可以输入类似以下的值:

code
1, 3-5, 8

在生成最终PDF之前,这些值将被转换为页面编号数组。

应用模糊效果

到目前为止,用户已上传PDF,选择了模糊区域,调整了模糊强度,并选择了需要处理的页面。

最后一步是将这些模糊区域转换为生成PDF中的实际模糊内容。

应用程序不会直接修改原始文档,而是创建新PDF的同时保留原始文件。

加载原始PDF

首先将上传的PDF加载到PDF-lib中。

code
async function applyBlur() {

    const pdfDoc =

        await PDFLib.PDFDocument.load(
            originalPdfBytes.slice()
        );

    const pages =
        pdfDoc.getPages();

}

使用原始字节的副本可以确保上传的文档保持不变。

处理选定页面

确定需要应用模糊效果的页面。

code
const selectedPages =

parsePageSelection(

    pageSelection,

    pdfDoc.getPageCount()

);
code
当前页面

↓

[2]

所有页面

↓

[1,2,3,4]

指定页面

↓

[1,3,5]

仅这些页面会在处理过程中被修改。

将每页渲染为图像

由于模糊是基于像素的效果,每个选定的PDF页面都会被渲染到离屏画布中。

code
const page =

await pdfDocument.getPage(
    pageNumber
);

const viewport =
page.getViewport({

    scale: 2

});

const canvas =
document.createElement(
    "canvas"
);

canvas.width =
viewport.width;

canvas.height =
viewport.height;
code
await page.render({

    canvasContext:
    canvas.getContext("2d"),

    viewport

}).promise;

现在画布中包含可以编辑的PDF页面位图版本。

对选定区域应用模糊

获取属于当前页面的所有模糊区域。

code
const pageRegions =

blurAreas.filter(

    area =>

        area.page === pageNumber

);

遍历每个模糊区域。

code
pageRegions.forEach(

    area => {

        blurCanvasRegion(

            canvas,

            area

        );

    }

);

每个区域独立进行模糊处理。

模糊画布区域

浏览器的 Canvas API 允许在绘制时应用滤镜。

根据所选强度设置模糊滤镜。

code
context.filter =

`blur(${area.intensity}px)`;

仅重绘所选区域。

code
context.drawImage(

    canvas,

    area.x,

    area.y,

    area.width,

    area.height,

    area.x,

    area.y,

    area.width,

    area.height

);

绘制完成后重置滤镜。

code
context.filter = "none";

仅所选矩形区域会被模糊,页面其余部分保持不变。

模糊整个页面

如果用户选择“模糊整个页面”,处理过程会简单得多。

对整个画布应用滤镜。

code
context.filter =

`blur(${blurIntensity}px)`;

context.drawImage(

    canvas,

    0,

    0

);

context.filter =
"none";

整个渲染页面会应用所选的模糊效果。

将画布转换回 PDF 图像

编辑完画布后,将其转换为图像。

code
const imageData =

canvas.toDataURL(
    "image/png"
);

将图像转换为字节。

code
const bytes =

await fetch(imageData)

.then(

response =>

response.arrayBuffer()

);

将图像嵌入 PDF-lib。

code
const image =

await pdfDoc.embedPng(
    bytes
);

替换页面内容。

code
const pdfPage =

pages[
pageNumber - 1
];

const size =
pdfPage.getSize();

pdfPage.drawImage(

    image,

    {

        x: 0,

        y: 0,

        width:
        size.width,

        height:
        size.height

    }

);

对每个选中的页面重复相同操作。

显示处理状态

生成大型 PDF 文件可能需要几秒钟。

处理期间显示加载状态。

code
applyButton.disabled =
true;

applyButton.textContent =
"Applying...";

处理完成后:

code
applyButton.disabled =
false;

applyButton.textContent =
"Apply & Finalize";

这为用户提供了明确的反馈,表明应用正在运行。

处理期间:

生成最终 PDF

所有页面处理完成后,保存完成的文档。

code
const pdfBytes =

await pdfDoc.save();

const outputBlob =
new Blob(

[pdfBytes],

{

type:
"application/pdf"

}

);

存储结果以便稍后预览和下载。

code
generatedPdfBlob =
outputBlob;

至此,模糊后的 PDF 已成功生成。

预览结果

隐藏编辑界面并显示完成的文档。

code
editorSection.hidden =
true;

resultSection.hidden =
false;

结果界面显示:

  • 最终 PDF 预览
  • 可编辑的文件名
  • 总页数
  • 文件大小
  • 下载按钮

用户可以在下载前查看处理后的文档。

重命名和下载

下载前,用户可能希望重命名生成的文件。

创建文件名输入框。

code
<input

type="text"

id="outputFilename"

value="blurred-document.pdf">

验证文件名。

code
function getFilename() {

    let filename =
    outputFilename.value.trim();

    if (!filename) {

        filename =
        "blurred-document.pdf";

    }

    if (
        !filename
        .toLowerCase()
        .endsWith(".pdf")
    ) {

        filename += ".pdf";

    }

    return filename;

}

显示附加文件信息。

code
pageCount.textContent =

`Pages:
${finalPdfDocument.numPages}`;

fileSize.textContent =

formatFileSize(
generatedPdfBlob.size
);

下载处理后的文档。

code
downloadButton
.addEventListener(

"click",

() => {

    const url =

    URL.createObjectURL(
        generatedPdfBlob
    );

    const link =
    document.createElement(
        "a"
    );

    link.href = url;

    link.download =
    getFilename();

    link.click();

    URL.revokeObjectURL(
        url
    );

});

浏览器直接下载完成的PDF文件,而无需将任何文件发送到远程服务器。

演示:PDF模糊工具的工作原理

让我们逐步了解完整的工作流程。

步骤1:上传PDF

用户通过拖放或点击“选择PDF”按钮上传PDF文件。

浏览器验证文件并准备渲染。

步骤2:预览文档

上传的PDF显示在预览窗口中。

用户可以使用页面导航控件在文档中切换页面。

步骤3:配置模糊设置

用户选择是对选中区域还是整页应用模糊效果。

在创建任何模糊区域之前,还可以配置模糊强度。

步骤4:绘制模糊区域

用户直接在PDF预览上点击拖拽,以在敏感内容上创建模糊矩形。

同一页面上可以创建多个模糊区域。

步骤5:调整模糊强度

模糊强度滑块控制模糊效果的强度。

数值越高,模糊效果越明显。

步骤6:管理模糊区域

可以删除单个模糊区域,或清除当前页面上的所有模糊区域。

这在生成最终PDF之前使编辑更加便捷。

步骤7:选择页面

用户决定模糊效果应用的页面范围:

  • 当前页面
code
1,3-5,8

步骤8:应用模糊效果

在确认设置后,用户点击“应用并完成”。

应用程序生成包含所选模糊效果的新PDF文件。

步骤9:查看最终文档

完成的PDF显示在预览窗口中。

用户可以在下载前验证所有模糊区域。

步骤10:重命名并下载

最后,用户可以重命名输出文件(如需),然后点击“下载”。

浏览器将完成的PDF保存到本地。

性能优化建议

大型PDF文件的渲染和处理可能需要更长时间,但通过一些简单的优化可以保持编辑器的响应性。

仅渲染用户当前查看的页面,而不是加载整个文档。

code
await renderPage(
    currentPage
);

重复使用相同的画布,在修改时仅重绘模糊区域。

code
overlayContext.clearRect(
    0,
    0,
    overlayCanvas.width,
    overlayCanvas.height
);

redrawBlurAreas();

在最终处理阶段,仅生成用户选择的页面。

code
for (const page of selectedPages) {

    await processPage(page);

}

最后,在下载完成后释放临时资源。

code
URL.revokeObjectURL(
    downloadUrl
);

这些优化减少了内存使用,使PDF模糊工具即使处理大型多页文档也能流畅运行。

常见错误

一个常见问题是,在考虑当前缩放级别之前就存储了模糊坐标。

在生成最终文档前,始终将预览坐标转换为PDF的坐标系统。

code
const scaleX =

pdfWidth /
canvas.width;

const scaleY =

pdfHeight /
canvas.height;

另一个错误是允许模糊区域超出页面边界。

在处理之前限制这些值。

code
blurArea.x = Math.max(
0,
blurArea.x
);

blurArea.y = Math.max(
0,
blurArea.y
);

用户在下载前还应验证最终预览效果,特别是在不同页面存在多个模糊区域时。

最后请记住,本项目仅对渲染的PDF页面应用视觉模糊效果。如果您的应用需要永久删除敏感内容而非仅视觉遮盖,则需要采用额外的文档脱敏技术。

结论

在本教程中,您使用JavaScript构建了一个基于浏览器的PDF模糊工具。

您学习了如何上传并预览PDF文档、在页面间导航、创建和管理多个模糊区域、调整模糊强度、对选定页面应用模糊效果、使用PDF-lib生成新的PDF文件、预览处理后的文档并下载最终文件——所有操作均无需将数据上传到服务器。

通过结合PDF.js、HTML Canvas API和PDF-lib,您创建了一个专注于隐私的PDF编辑工具,该工具完全在浏览器内部运行。

您可以使用PDF模糊工具探索完整的操作流程。

从这里开始,您可以为该项目添加更多功能,例如可移动和可调整大小的模糊区域、撤销/重做支持、可重复使用的模糊预设、键盘快捷键、触屏设备编辑功能,或更多高级的基于浏览器的PDF编辑注释工具。

AllInOneTools.net创始人 —— 开发简单、免费、无需登录的网络工具,解决日常问题。我专注于实用工具、SEO、提高效率,并公开发布有用的软件。在构建和扩展AllInOneTools的过程中,我根据真实经验进行写作。

如果您读到这里,请感谢作者以表达您的支持。说声谢谢

免费学习编程。freeCodeCamp的开源课程已帮助超过40,000人成为开发者。立即开始

ADVERTISEMENT