前端獲取二進(jìn)制文件并預(yù)覽功能的完整指南
前言
在前端開發(fā)中,我們經(jīng)常需要處理后端返回的二進(jìn)制文件,比如PDF、圖片、Excel等。本文將詳細(xì)介紹如何在前端獲取二進(jìn)制文件并實(shí)現(xiàn)預(yù)覽功能。
一、什么是二進(jìn)制文件?
二進(jìn)制文件是以二進(jìn)制格式存儲(chǔ)的文件,與文本文件不同,它不能直接以文本形式查看。常見的二進(jìn)制文件包括:
- PDF文檔
- 圖片(JPG、PNG、GIF等)
- Office文檔(Word、Excel、PPT)
- 壓縮包(ZIP、RAR)
- 音視頻文件
二、后端接口配置
1. 后端返回二進(jìn)制數(shù)據(jù)
后端需要設(shè)置正確的響應(yīng)頭:
// Spring Boot 示例
@PostMapping("/previewPDF")
public ResponseEntity<byte[]> previewPDF(@RequestBody Map<String, Object> params) {
byte[] pdfBytes = pdfService.generatePDF(params);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDispositionFormData("inline", "preview.pdf");
return new ResponseEntity<>(pdfBytes, headers, HttpStatus.OK);
}
2. 前端接口定義
使用axios時(shí),需要設(shè)置responseType: 'blob':
// api/file.js
import request from '@/utils/request'
export function previewPDF(data) {
return request({
url: '/api/pdf/preview',
method: 'post',
data: data,
responseType: 'blob' // 關(guān)鍵配置:告訴axios以二進(jìn)制方式接收數(shù)據(jù)
})
}
三、前端處理二進(jìn)制數(shù)據(jù)
1. 基礎(chǔ)概念
Blob對(duì)象:Blob(Binary Large Object)表示一個(gè)不可變的、原始數(shù)據(jù)的類文件對(duì)象。
URL.createObjectURL():創(chuàng)建一個(gè)指向Blob對(duì)象的臨時(shí)URL。
2. 完整實(shí)現(xiàn)代碼
// 預(yù)覽PDF的完整方法
async previewPDF() {
try {
// 1. 顯示加載提示
const loading = this.$loading({
lock: true,
text: '正在生成預(yù)覽...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
// 2. 調(diào)用接口獲取二進(jìn)制數(shù)據(jù)
const blob = await previewPDF({
id: this.reportId,
type: 'preview'
})
// 3. 創(chuàng)建Blob對(duì)象
const pdfBlob = new Blob([blob], {
type: 'application/pdf'
})
// 4. 創(chuàng)建臨時(shí)URL
const blobUrl = window.URL.createObjectURL(pdfBlob)
// 5. 在新窗口中打開
window.open(blobUrl, '_blank')
// 6. 延遲釋放URL(給瀏覽器足夠時(shí)間加載)
setTimeout(() => {
window.URL.revokeObjectURL(blobUrl)
}, 100)
loading.close()
this.$message.success('PDF預(yù)覽已打開')
} catch (error) {
console.error('預(yù)覽失敗:', error)
this.$message.error('預(yù)覽失敗,請(qǐng)重試')
}
}
四、不同文件類型的處理
1. PDF文件預(yù)覽
// PDF預(yù)覽
function previewPDF(blob) {
const pdfBlob = new Blob([blob], { type: 'application/pdf' })
const url = window.URL.createObjectURL(pdfBlob)
window.open(url, '_blank')
setTimeout(() => window.URL.revokeObjectURL(url), 100)
}
2. 圖片預(yù)覽
// 圖片預(yù)覽
function previewImage(blob) {
const imageBlob = new Blob([blob], { type: 'image/jpeg' })
const url = window.URL.createObjectURL(imageBlob)
// 方式1:新窗口打開
window.open(url, '_blank')
// 方式2:在img標(biāo)簽中顯示
const img = document.createElement('img')
img.src = url
document.body.appendChild(img)
// 記得釋放URL
img.onload = () => {
window.URL.revokeObjectURL(url)
}
}
3. Excel文件下載
// Excel下載
function downloadExcel(blob, filename) {
const excelBlob = new Blob([blob], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
const url = window.URL.createObjectURL(excelBlob)
// 創(chuàng)建a標(biāo)簽觸發(fā)下載
const link = document.createElement('a')
link.href = url
link.download = filename || 'download.xlsx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
// 釋放URL
window.URL.revokeObjectURL(url)
}
4. Word文檔下載
// Word下載
function downloadWord(blob, filename) {
const wordBlob = new Blob([blob], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
const url = window.URL.createObjectURL(wordBlob)
const link = document.createElement('a')
link.href = url
link.download = filename || 'document.docx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
}
五、常見MIME類型對(duì)照表
| 文件類型 | MIME類型 |
|---|---|
| application/pdf | |
| JPG/JPEG | image/jpeg |
| PNG | image/png |
| GIF | image/gif |
| Excel (.xlsx) | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
| Excel (.xls) | application/vnd.ms-excel |
| Word (.docx) | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
| Word (.doc) | application/msword |
| ZIP | application/zip |
| TXT | text/plain |
六、Vue完整示例
<template>
<div>
<el-button @click="handlePreview" type="primary">預(yù)覽PDF</el-button>
<el-button @click="handleDownload" type="success">下載PDF</el-button>
</div>
</template>
<script>
import { previewPDF } from '@/api/file'
export default {
data() {
return {
fileId: '123456'
}
},
methods: {
// 預(yù)覽
async handlePreview() {
try {
const loading = this.$loading({
lock: true,
text: '正在加載...'
})
const blob = await previewPDF({ id: this.fileId })
const url = window.URL.createObjectURL(
new Blob([blob], { type: 'application/pdf' })
)
window.open(url, '_blank')
setTimeout(() => {
window.URL.revokeObjectURL(url)
}, 100)
loading.close()
} catch (error) {
this.$message.error('預(yù)覽失敗')
}
},
// 下載
async handleDownload() {
try {
const loading = this.$loading({
lock: true,
text: '正在下載...'
})
const blob = await previewPDF({ id: this.fileId })
const url = window.URL.createObjectURL(
new Blob([blob], { type: 'application/pdf' })
)
const link = document.createElement('a')
link.href = url
link.download = 'report.pdf'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
loading.close()
this.$message.success('下載成功')
} catch (error) {
this.$message.error('下載失敗')
}
}
}
}
</script>
七、常見問題及解決方案
1. 問題:接口返回亂碼
原因:沒有設(shè)置responseType: 'blob'
解決:
// 錯(cuò)誤寫法
export function previewPDF(data) {
return request({
url: '/api/pdf/preview',
method: 'post',
data: data
// 缺少 responseType: 'blob'
})
}
// 正確寫法
export function previewPDF(data) {
return request({
url: '/api/pdf/preview',
method: 'post',
data: data,
responseType: 'blob' // 必須添加
})
}
2. 問題:PDF在新窗口無(wú)法打開
原因:瀏覽器攔截了彈窗
解決:
// 方式1:提示用戶允許彈窗
window.open(url, '_blank')
// 方式2:使用iframe在當(dāng)前頁(yè)面顯示
const iframe = document.createElement('iframe')
iframe.src = url
iframe.style.width = '100%'
iframe.style.height = '600px'
document.body.appendChild(iframe)
3. 問題:內(nèi)存泄漏
原因:創(chuàng)建的URL沒有及時(shí)釋放
解決:
// 記得釋放URL const url = window.URL.createObjectURL(blob) // ... 使用URL window.URL.revokeObjectURL(url) // 使用完后釋放
4. 問題:下載的文件名亂碼
解決:
// 從響應(yīng)頭獲取文件名
function getFileNameFromResponse(response) {
const disposition = response.headers['content-disposition']
if (disposition) {
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition)
if (matches && matches[1]) {
return decodeURIComponent(matches[1].replace(/['"]/g, ''))
}
}
return 'download.pdf'
}
八、性能優(yōu)化建議
1. 大文件處理
// 對(duì)于大文件,使用流式下載
async function downloadLargeFile(url) {
const response = await fetch(url)
const reader = response.body.getReader()
const chunks = []
while (true) {
const { done, value } = await reader.read()
if (done) break
chunks.push(value)
}
const blob = new Blob(chunks)
// 處理blob...
}
2. 添加進(jìn)度提示
async function downloadWithProgress(url, onProgress) {
const response = await fetch(url)
const total = response.headers.get('content-length')
const reader = response.body.getReader()
let loaded = 0
const chunks = []
while (true) {
const { done, value } = await reader.read()
if (done) break
chunks.push(value)
loaded += value.length
if (onProgress) {
onProgress({ loaded, total })
}
}
return new Blob(chunks)
}
九、總結(jié)
處理二進(jìn)制文件的關(guān)鍵步驟:
- 接口配置:設(shè)置
responseType: 'blob' - 創(chuàng)建Blob:
new Blob([data], { type: 'mime-type' }) - 創(chuàng)建URL:
URL.createObjectURL(blob) - 使用URL:預(yù)覽或下載
- 釋放資源:
URL.revokeObjectURL(url)
掌握這些技巧,你就能輕松處理各種二進(jìn)制文件了!
參考資料
到此這篇關(guān)于前端獲取二進(jìn)制文件并預(yù)覽功能的完整指南的文章就介紹到這了,更多相關(guān)前端獲取二進(jìn)制文件預(yù)覽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS/jQuery實(shí)現(xiàn)默認(rèn)顯示部分文字點(diǎn)擊按鈕顯示全部?jī)?nèi)容
默認(rèn)顯示部分文字,點(diǎn)擊按鈕顯示全部,類似這樣的功能在一些特殊的地方會(huì)見到吧,下面與大家分享下JS、jQuery如何實(shí)現(xiàn),感興趣的朋友可以參考下哈,希望對(duì)你有所幫助2013-05-05
防止Layui form表單重復(fù)提交的實(shí)現(xiàn)方法
今天小編就為大家分享一篇防止Layui form表單重復(fù)提交的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2019-09-09
文字溢出實(shí)現(xiàn)溢出的部分再放入一個(gè)新生成的div中具體代碼
說(shuō)文字溢出,如何實(shí)現(xiàn)溢出的文字放入一個(gè)新生成的div中,原理就是判斷是否能在div里放下,如果不能,則在應(yīng)該斷開的地方,差入到新的div中2013-05-05
前端使用WebSocket進(jìn)行實(shí)時(shí)數(shù)據(jù)通信的實(shí)現(xiàn)方法
在現(xiàn)代 Web 開發(fā)中,實(shí)時(shí)通信已成為提升用戶體驗(yàn)的關(guān)鍵技術(shù)之一,WebSocket 作為一種在單個(gè) TCP 連接上進(jìn)行全雙工通信的協(xié)議,為前端實(shí)現(xiàn)實(shí)時(shí)通信提供了強(qiáng)大的支持,本文將深入探討如何在前端使用 WebSocket 實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)通信,需要的朋友可以參考下2025-05-05
javascript實(shí)現(xiàn)時(shí)間格式輸出FormatDate函數(shù)
這篇文章主要介紹了javascript實(shí)現(xiàn)時(shí)間格式輸出FormatDate函數(shù),可實(shí)現(xiàn)fmt標(biāo)簽一樣對(duì)日期時(shí)間型內(nèi)容格式輸入的功能,是非常實(shí)用的技巧,需要的朋友可以參考下2015-01-01
JavaScript中使用import 和require打包后實(shí)現(xiàn)原理分析
這篇文章主要介紹了JavaScript中使用import 和require打包后實(shí)現(xiàn)原理分析,需要的朋友可以參考下2018-03-03

