utils.js 3.91 KB
/**
 * @Description: 文档预览工具函数
 * @Date: 2025-01-30
 */

// #ifdef WEAPP
import Taro from '@tarojs/taro'
// #endif

/**
 * 从 URL 中检测文件类型
 * @param {string} url - 文档 URL
 * @returns {string} 文件类型(小写)
 */
export function detectFileType(url) {
  if (!url) return ''

  // 从 URL 中提取扩展名
  const match = url.match(/\.([a-z0-9]+)(?:\?|#|$)/i)

  if (match && match[1]) {
    const ext = match[1].toLowerCase()

    // 映射常见扩展名到统一类型
    const typeMap = {
      pdf: 'pdf',
      doc: 'doc',
      docx: 'docx',
      xls: 'xls',
      xlsx: 'xlsx',
      ppt: 'ppt',
      pptx: 'pptx'
    }

    return typeMap[ext] || ext
  }

  // 如果无法从 URL 判断,尝试从 Content-Type 头(需要后端支持)
  return ''
}

/**
 * 获取文件大小(通过 HEAD 请求)
 * @param {string} url - 文档 URL
 * @returns {Promise<number>} 文件大小(字节)
 */
export async function getFileSize(url) {
  return new Promise((resolve) => {
    // #ifdef H5
    // H5 环境:使用 fetch HEAD 请求
    fetch(url, { method: 'HEAD' })
      .then(response => {
        const contentLength = response.headers.get('Content-Length')
        if (contentLength) {
          resolve(parseInt(contentLength, 10))
        } else {
          // 无法获取大小,返回 0(将使用 web-view)
          resolve(0)
        }
      })
      .catch(err => {
        console.error('获取文件大小失败:', err)
        // 失败时返回 0,将使用 web-view
        resolve(0)
      })
    // #endif

    // #ifdef WEAPP
    // 小程序环境:使用 Taro.request HEAD 请求
    Taro.request({
      url: url,
      method: 'HEAD',
      success: (res) => {
        const contentLength = res.header['Content-Length'] || res.header['content-length']
        if (contentLength) {
          resolve(parseInt(contentLength, 10))
        } else {
          // 无法获取大小,返回 0(将使用 web-view)
          resolve(0)
        }
      },
      fail: (err) => {
        console.error('获取文件大小失败:', err)
        // 失败时返回 0,将使用 web-view
        resolve(0)
      }
    })
    // #endif
  })
}

/**
 * 格式化文件大小显示
 * @param {number} bytes - 文件大小(字节)
 * @returns {string} 格式化后的字符串
 */
export function formatFileSize(bytes) {
  if (!bytes || bytes === 0) return '未知大小'

  const units = ['B', 'KB', 'MB', 'GB']
  let size = bytes
  let unitIndex = 0

  while (size >= 1024 && unitIndex < units.length - 1) {
    size /= 1024
    unitIndex++
  }

  // 保留两位小数
  const formatted = size.toFixed(2).replace(/\.00$/, '')

  return `${formatted} ${units[unitIndex]}`
}

/**
 * 判断是否为支持的文档类型
 * @param {string} fileType - 文件类型
 * @returns {boolean}
 */
export function isSupportedDocumentType(fileType) {
  const supportedTypes = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
  return supportedTypes.includes(fileType?.toLowerCase())
}

/**
 * 获取文件图标名称
 * @param {string} fileType - 文件类型
 * @returns {string} 图标名称
 */
export function getFileIconName(fileType) {
  const iconMap = {
    pdf: 'pdf',
    doc: 'word',
    docx: 'word',
    xls: 'excel',
    xlsx: 'excel',
    ppt: 'ppt',
    pptx: 'ppt'
  }
  return iconMap[fileType?.toLowerCase()] || 'file'
}

/**
 * 生成腾讯文档预览 URL
 * @param {string} url - 原始文档 URL
 * @returns {string} 腾讯文档预览 URL
 */
export function getTencentPreviewUrl(url) {
  const encodedUrl = encodeURIComponent(url)
  return `https://view.officeapps.live.com/op/view.aspx?src=${encodedUrl}`
}

/**
 * 生成微软在线预览 URL
 * @param {string} url - 原始文档 URL
 * @returns {string} 微软预览 URL
 */
export function getMicrosoftPreviewUrl(url) {
  const encodedUrl = encodeURIComponent(url)
  return `https://view.officeapps.live.com/op/embed.aspx?src=${encodedUrl}`
}