文件预览+下载

225 阅读2分钟
  1. 介绍

    • 发现谷歌浏览器默认可以直接预览部分格式的文件,例如pdf,png,txt...但是开发的时候发现一个问题,给的二进制流文件需要加一个Blob对应的type才能预览,后端提供的接口并没有给文件Blob对应的type,所以只能前端加上type,才能正常预览
  2. 实现步骤

    • 步骤一:获取文件后缀,获取正确的Blob对应的type
    • 步骤二:谷歌浏览器是否支持预览,不支持预览则下载该文件
  3. 代码解释

获取Blob对应的type

/**
 * 可预览列表
 * 谷歌浏览器 可以直接预览部分文件
 * 但是转化的 blob 对象 需要提供正确的type
 * @param name 带后缀的文件名
 * @returns
 */
export const fileNameViewer = (name: string): string => {
  let type = getFileExtension(name)
  const typeMap = {
    pdf: 'application/pdf',
    png: 'image/png',
    jpg: 'image/jpeg',
    jpeg: 'image/jpeg',
    txt: 'text/plain;charset=utf-8',
    json: 'application/json',
    mp3: 'audio/mpeg'
  }
  return typeMap[type] || 'Unknown'
}
/**
 * 获取文件名后缀
 * @param fileName 文件名
 * @returns 后缀
 */
function getFileExtension(fileName: string): string {
  const lastDotIndex = fileName.lastIndexOf('.')
  // 检查是否存在点号,且不在字符串的开头
  if (lastDotIndex !== -1 && lastDotIndex < fileName.length - 1) {
    return fileName.slice(lastDotIndex + 1)
  } else {
    return '' // 文件名中没有后缀
  }
}

预览文件

/**
 * @param data 二进制流文件
 * @param name 文件名
 */
export const fileView = (data, name) => {
  let type = fileNameViewer(name)
  // 预览 如果 文件后缀不支持预览,则直接下载
  if (type !== 'Unknown') {
    // 加 type, 没有类型的话,
    const blob = new Blob([data], { type })
    let url = URL.createObjectURL(blob)
    window.open(url, '_blank')
  } else {
    fileDownLoad(data, name)
  }
}

/**
 * 文件下载
 * @param data blob二进制流
 * @param name 文件名
 * @returns
 */
export const fileDownLoad = (data, name) => {
  if (!data) {
    console.log('data不能为空')
    return
  }
  if (!name) {
    console.log('name不能为空')
    return
  }
  const a = document.createElement('a')
  a.download = name
  a.style.display = 'none'
  let url = URL.createObjectURL(data)
  a.href = url
  document.body.appendChild(a)
  a.click()
  URL.revokeObjectURL(a.href)
  document.body.removeChild(a)
  elMessage('导出成功...')
}
  1. 实际应用

const onPreview = async (UploadFile) => {
  try {
    let name = UploadFile.fileName || UploadFile.name
    let id = UploadFile.response.data.id
    // 这边接口获取的就是blob文件流
    let { data } = await fileDownloadFile({ id })
    // 调用预览方法
    fileView(data, name)
  } catch (error) {
    console.log('🐷 🐽 onPreview 🐽 error👉👉👉', error)
  }
}