HTML 原生标签(如 <img src="...">)发起的请求是由浏览器自动处理的,开发者无法干预其请求头。这是出于安全和简洁性的设计考量。因此,若服务器要求特定请求头(如 JWT Token),直接使用 <img> 将导致 401/403 错误。
PDF 文件通常通过 <iframe> 渲染。与图片类似,这些标签也无法携带请求头。我们可以用相同思路:先获取 PDF 的二进制流,再生成可嵌入的 URL。
实现步骤
图片
-
使用
fetch请求图片资源,并在headers中添加认证信息; -
将响应转为
Blob对象; -
通过
URL.createObjectURL(blob)生成本地 URL; -
将该 URL 赋给
<img>的src属性; -
图片加载完成后,调用
URL.revokeObjectURL()释放内存。
示例代码
不讲屁话,全是干货!Talk is cheap, show you the code !
async function loadImageWithAuth(url, token, imgElement) {
try {
const res = await fetch(url, {
headers: {
Authorization: 'Bearer ' + token
}
});
if (!res.ok) throw new Error('Failed to load image');
const blob = await res.blob();
const objectUrl = URL.createObjectURL(blob);
imgElement.src = objectUrl;
// 清理内存:图片加载完成后释放 Blob URL
imgElement.onload = () => {
URL.revokeObjectURL(objectUrl);
};
} catch (error) {
console.error('Error loading image:', error);
imgElement.src = ''; // 可选:显示占位图或错误提示
}
}
// 使用示例
const img = document.getElementById('protected-image');
loadImageWithAuth('https://api.example.com/image.jpg', 'your-jwt-token', img);
-
用
fetch获取 PDF 资源(带Authorization头); -
读取
response.body的ReadableStream; -
将流数据分块收集并合并为
Blob; -
创建
Blob URL并赋给<iframe>的src。
示例代码
不讲屁话,全是干货!Talk is cheap, show you the code !
async function loadPdfWithAuth(url, token, iframeElement) {
try {
const res = await fetch(url, {
headers: {
Authorization: 'Bearer ' + token
}
});
if (!res.ok) throw new Error('Failed to load PDF');
const reader = res.body.getReader();
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
const blob = new Blob(chunks, { type: 'application/pdf' });
const objectUrl = URL.createObjectURL(blob);
iframeElement.src = objectUrl;
// 清理内存
iframeElement.onload = () => {
URL.revokeObjectURL(objectUrl);
};
} catch (error) {
console.error('Error loading PDF:', error);
iframeElement.src = ''; // 或跳转到错误页面
}
}
// 使用示例
const pdfIframe = document.getElementById('pdf-preview');
loadPdfWithAuth('https://api.example.com/report.pdf', 'your-jwt-token', pdfIframe);