Loading... 在前端开发中,处理PDF流文件并下载或在新窗口中打开是一种常见的需求。`XMLHttpRequest`可以用于获取PDF的二进制流数据,而 `window.open`则可以用于在新窗口中展示PDF文件。本文将详细介绍如何使用这两个技术处理PDF文件的流式下载和展示,确保满足实际业务需求。 ## 一、使用 `XMLHttpRequest`获取PDF流文件 ### 1.1 `XMLHttpRequest`获取二进制数据 `XMLHttpRequest`是一种浏览器API,用于从服务器获取数据。为了获取PDF文件这种二进制数据,需要将 `responseType`设置为 `blob`,表示接收二进制的Blob数据格式。 以下是使用 `XMLHttpRequest`获取PDF流文件的基础步骤: ```javascript function fetchPDF(url) { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'blob'; // 指定响应类型为 blob 二进制文件 xhr.onload = function() { if (xhr.status === 200) { // 请求成功,处理PDF文件 const pdfBlob = xhr.response; handlePDF(pdfBlob); } else { console.error('Failed to load PDF:', xhr.status); } }; xhr.onerror = function() { console.error('An error occurred during the request.'); }; xhr.send(); } ``` **解释**: - `xhr.responseType = 'blob'`:告诉 `XMLHttpRequest`接收二进制文件。 - `xhr.onload`:当请求成功完成时,通过 `xhr.response`获取PDF文件的 `Blob`对象。 - `xhr.send()`:发送HTTP请求。 ### 1.2 处理Blob对象 获取到 `Blob`对象后,可以选择将其下载到用户的本地设备,或在新窗口中直接展示。 ## 二、将PDF流文件下载 ### 2.1 使用 `URL.createObjectURL`实现下载 `URL.createObjectURL`可以将 `Blob`对象转换为一个临时的URL,随后可以用这个URL实现文件的下载。代码如下: ```javascript function downloadPDF(pdfBlob) { // 创建一个临时的 URL const url = URL.createObjectURL(pdfBlob); // 创建一个隐藏的 <a> 标签,并触发点击事件实现下载 const a = document.createElement('a'); a.href = url; a.download = 'downloaded_file.pdf'; // 指定下载的文件名 document.body.appendChild(a); a.click(); // 释放 URL 对象 URL.revokeObjectURL(url); } ``` **解释**: - `URL.createObjectURL(pdfBlob)`:将 `Blob`对象转换为临时URL。 - 创建一个隐藏的 `<a>`元素并触发 `click`事件,自动下载文件。 - `a.download`:设置下载文件的名称。 - `URL.revokeObjectURL(url)`:释放URL对象,避免内存泄漏。 ### 2.2 调用下载方法 可以通过在 `XMLHttpRequest`完成后,调用下载方法: ```javascript function handlePDF(pdfBlob) { downloadPDF(pdfBlob); } ``` ### 2.3 下载流程图 ```mermaid graph TD A[发送XHR请求] --> B{请求成功?} B -- 是 --> C[获取Blob对象] C --> D[创建临时URL] D --> E[创建<a>标签] E --> F[触发下载] F --> G[释放URL] B -- 否 --> H[处理错误] ``` ## 三、在新窗口中打开PDF ### 3.1 使用 `window.open`打开PDF 除了下载PDF,另一种常见的需求是直接在新窗口中打开PDF文件。可以利用 `window.open`打开一个新的窗口,并将 `Blob`对象转换为URL展示PDF。 ```javascript function openPDFInNewWindow(pdfBlob) { // 将 Blob 转换为临时 URL const url = URL.createObjectURL(pdfBlob); // 在新窗口中打开 PDF window.open(url); // 可以在合适的时机释放 URL 对象 URL.revokeObjectURL(url); } ``` **解释**: - `window.open(url)`:在新窗口中打开PDF文件。 - `URL.revokeObjectURL(url)`:释放临时URL,避免内存泄漏。 ### 3.2 使用 `window.open`的场景 对于用户需要在线预览PDF的场景,这种方法非常适合。例如在一个文档管理系统中,用户可以点击按钮直接预览PDF文件而不必下载。 ### 3.3 打开PDF的流程图 ```mermaid graph TD A[发送XHR请求] --> B{请求成功?} B -- 是 --> C[获取Blob对象] C --> D[创建临时URL] D --> E[window.open展示PDF] E --> F[释放URL] B -- 否 --> G[处理错误] ``` ## 四、处理跨域问题 ### 4.1 设置CORS头信息 在从另一个域名获取PDF文件时,可能会遇到跨域资源共享(CORS)问题。为解决这个问题,服务器需要在响应头中添加适当的CORS头信息: ```http Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Headers: Content-Type ``` ### 4.2 使用 `withCredentials`处理认证 如果需要发送带有认证信息的跨域请求,可以在 `XMLHttpRequest`中设置 `withCredentials`属性: ```javascript xhr.withCredentials = true; ``` ## 五、完整代码示例 以下是完整的代码,展示了如何从服务器获取PDF流文件,并提供用户选择下载或打开PDF的功能: ```javascript function fetchPDF(url) { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'blob'; // 指定响应类型为 blob xhr.onload = function() { if (xhr.status === 200) { const pdfBlob = xhr.response; // 处理下载或打开PDF const userChoice = prompt('请输入 "download" 进行下载,或者 "open" 在新窗口打开:'); if (userChoice === 'download') { downloadPDF(pdfBlob); } else if (userChoice === 'open') { openPDFInNewWindow(pdfBlob); } } else { console.error('Failed to load PDF:', xhr.status); } }; xhr.onerror = function() { console.error('An error occurred during the request.'); }; xhr.send(); } function downloadPDF(pdfBlob) { const url = URL.createObjectURL(pdfBlob); const a = document.createElement('a'); a.href = url; a.download = 'downloaded_file.pdf'; document.body.appendChild(a); a.click(); URL.revokeObjectURL(url); } function openPDFInNewWindow(pdfBlob) { const url = URL.createObjectURL(pdfBlob); window.open(url); URL.revokeObjectURL(url); } // 调用示例 fetchPDF('https://example.com/sample.pdf'); ``` **解释**: - 通过 `prompt`提示用户选择操作,用户可以选择下载PDF或在新窗口中打开PDF。 - `downloadPDF`函数用于下载PDF文件。 - `openPDFInNewWindow`函数用于在新窗口中展示PDF。 ## 六、优化与扩展 ### 6.1 添加进度条显示 在下载较大的PDF文件时,用户体验可能会受到影响。可以利用 `XMLHttpRequest`的 `onprogress`事件实现下载进度条显示。 ```javascript xhr.onprogress = function(event) { if (event.lengthComputable) { const percentComplete = (event.loaded / event.total) * 100; console.log(`Download progress: ${percentComplete}%`); // 可以在页面上展示进度条 } }; ``` ### 6.2 处理大文件 对于非常大的PDF文件,可以考虑将Blob文件部分加载或实现流式下载,以减少页面加载压力。 ### 6.3 错误处理优化 在生产环境中,进一步优化错误处理,提供友好的用户提示或重试机制。例如,可以根据错误代码展示不同的提示信息: ```javascript xhr.onerror = function() { alert('PDF文件加载失败,请检查网络连接或稍后再试。'); }; ``` ## 七、分析说明表 | 步骤 | 说明 | 代码或方法示例 | | ------------- | --------------------------------------------- | ------------------------------------ | | 发送请求 | 通过 `XMLHttpRequest`发送GET请求获取PDF文件 | `xhr.open('GET', url, true);` | | 处理响应 | 获取二进制流数据并处理为Blob对象 | `xhr.responseType = 'blob';` | | 文件下载 | 将Blob对象转换为URL,并触发文件下载 | `URL.createObjectURL(pdfBlob);` | | 新窗口打开PDF | 将Blob对象转换为URL,并在新窗口打开 | `window.open(URL.createObjectURL)` | | 错误处理 | 请求失败时处理错误,输出或提示用户 | `xhr.onerror = function() | 最后修改:2024 年 09 月 20 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏