需求场景:后端返回一个PDF文件(或者图片)的url地址,需要在PC端下载,在H5页面打开?
现像:浏览器中直接访问 PDF 文件和图片文件地址,打开后都直接下载了
// PDF 地址
https://carbonfile-dev.pek3b.qingstor.com/IRECPack1710468416132/IRECPack171046841613244/IRECPack1710468416132.pdf?access_key_id=XIRRTPOHDWJFHYYUZHLU&expires=1712803323&signature=Rc0usBuNoqVPL%2FSn1lUA3Xih1mYhhvkHfwyD%2BUlzddo%3D
// 图片地址
https://qkbwe-esg-dev.pek3b.qingstor.com/channel-O1711620818016/channel/2.png
分析如下
-
查看浏览器网络请求发现信息如下:
查看响 应头发现,两个文件中,Content-Disposition:都设置成了attachment,这是后端配置了响应参数,实现的浏览器自动下载方式。浏览器会直接下载
结论:后端返回的url地址是直接进行文件下载的,如果想要预览,需要另行处理
Content-disposition & Content-Type
-
Content-Type:文件类型
Content-Type:application/pdf,pdf文件
Content-Type:image/png,图片
-
Content-disposition
1)inline
默认情况下,浏览器设定是inline形式,对于服务器返回的文件,能打开就打开,不能打开就自动下载
特别说明:Chrome不设置Content-Type也会自动打开,如果是它可识别预览的文件
设置为inline,如果浏览器支持该文件类型的预览,就会打开,而不是下载:
response.setHeader("Content-Disposition", "inline; filename=111.jpg");
2)attachment
设置为 attachment ,浏览器不区分文件格式直接进行下载,纵使他能够预览该类型的文件。
response.setHeader("Content-Disposition", "attachment; filename=111.jpg");
下载方式:
2.1)window.open(url)
2.2)创建 a链接
文件预览
/** 将网络文件转成base64 */
export const urlToBase64 = async (url: string): Promise<any> => {
return new Promise((resolve, reject) => {
fetch(url)
.then((response) => response.blob())
.then((blob) => {
// 转换为 base64
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onloadend = () => {
resolve(reader.result)
}
})
.catch((error) => {
console.log(error)
reject()
})
})
}
/** base64 转成文件 */
export const dataURLtoFile = (dataurl: string, filename: string) => {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
}
// 预览
urlToBase64(pdfUrl).then((data) => {
const file = dataURLtoFile(data, pdfUrl)
const URL = window.URL.createObjectURL(file)
setPath(URL) // 预览的url地址
})
- 图片