Skip to content
小沐沐吖

Web 生成文件 URL

412 字约 1 分钟

2024-10-08

用途:文件下载、图片预览等

1、Blob[Blob URL]

axios
  .get("/api/file/202409270925510140b9f478123a47ef", {
    responseType: "arraybuffer",
  })
  .then((res) => {
    // 常见的文件类型
    // image/*
    // application/pdf
    // video/*
    // audio/*
    const url = URL.createObjectURL(
      new Blob([res.data], { type: "application/pdf" })
    );
    return url;
  });

2、Data URL

axios
  .get("/api/file/202409270925510140b9f478123a47ef", {
    responseType: "arraybuffer",
  })
  .then((res) => {
    return new Promise((resolve, reject) => {
      const fileReader = new FileReader();
      fileReader.onloadend = () => {
        resolve(fileReader.result);
      };

      // 常见的文件类型
      // image/*
      // application/pdf
      // video/*
      // audio/*
      fileReader.readAsDataURL(new Blob([res.data], { type: "image/*" }));
    });
  });

3、File Util

/**
 * 文件工具类
 */

// 定义文件扩展名和MIME类型的映射
const MIME_TYPE_MAP = {
  jpg: "image/jpeg",
  jpeg: "image/jpeg",
  png: "image/png",
  gif: "image/gif",
  bmp: "image/bmp",
  svg: "image/svg+xml",
  mp4: "video/mp4",
  mov: "video/quicktime",
  avi: "video/x-msvideo",
  mkv: "video/x-matroska",
  wmv: "video/x-ms-wmv",
  mp3: "audio/mpeg",
  wav: "audio/wav",
  aac: "audio/aac",
  flac: "audio/flac",
  ogg: "audio/ogg",
  pdf: "application/pdf",
  doc: "application/msword",
  docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  xls: "application/vnd.ms-excel",
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  ppt: "application/vnd.ms-powerpoint",
  pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  txt: "text/plain",
  json: "application/json",
  xml: "application/xml",
  zip: "application/zip",
  rar: "application/x-rar-compressed",
};

/**
 * 将文件或ArrayBuffer转换为Bolb
 * @param {File | ArrayBuffer} file
 * @param {string} [filePath]
 */
export const fileToBolb = (file, filePath) => {
  let type = "image/*";
  if (file instanceof File) {
    type = file.type;
  }
  if (filePath) {
    const extension = getFileExtension(filePath);
    type = inferFileType(extension) || type;
  }
  return new Blob([file], { type });
};

/**
 * 将文件或ArrayBuffer转换为BolbUrl,记得使用完要释放URL.createObjectURL
 * @param {File | ArrayBuffer} file
 * @param {string} [filePath]
 */
export const fileToBolbUrl = (file, filePath) => {
  return URL.createObjectURL(fileToBolb(file, filePath));
};

/**
 * 将文件或ArrayBuffer转换为DataURL
 * @param {File | ArrayBuffer} file
 * @param {string} [filePath]
 */
export const fileToDataUrl = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(fileToBolb(file, filePath));
  });
};

/**
 * 获取文件扩展名
 * @param {String} filePath
 * @returns
 */
function getFileExtension(filePath) {
  const match = filePath.match(/\.([^.]+)$/);
  if (!match) {
    return "";
  }
  return match[1];
}

/**
 * 根据文件扩展名推断文件MIME类型
 * @param {string} fileExtension
 * @returns {string|null}
 */
function inferFileType(fileExtension) {
  fileExtension = fileExtension.toLowerCase();

  if (MIME_TYPE_MAP.hasOwnProperty(fileExtension)) {
    return MIME_TYPE_MAP[fileExtension];
  }
  return null;
}