upload.js 3.08 KB
import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common';
import BMF from 'browser-md5-file';
// import { v4 as uuidv4 } from 'uuid';

// 获取文件后缀
const getFileSuffix = (fileName) => {
  return /.[^.]+$/.exec(fileName) || '';
};

// 获取文件MD5
const getFileMD5 = (file) => {
  return new Promise((resolve, reject) => {
    const bmf = new BMF();
    bmf.md5(file, (err, md5) => {
      if (err) {
        reject(err);
        return;
      }
      resolve(md5);
    });
  });
};

// 上传文件到七牛云
const uploadToQiniu = async (file, token, fileName, onProgress) => {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('token', token);
  formData.append('key', fileName);

  const config = {
    headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: (progressEvent) => {
      if (progressEvent.total > 0) {
        const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        // 使用requestAnimationFrame确保进度更新的平滑性
        requestAnimationFrame(() => {
          onProgress?.(percent);
        });
      }
    }
  };

  // 根据协议选择上传地址
  const qiniuUploadUrl = window.location.protocol === 'https:'
    ? 'https://up.qbox.me'
    : 'http://upload.qiniu.com';

  return await qiniuUploadAPI(qiniuUploadUrl, formData, config);
};

// 校验文件
export const validateFile = (file, options = {}) => {
  const {
    maxSize = 100,  // 默认100MB
    allowedTypes = ['video/mp4', 'video/quicktime'],
  } = options;

  if (!allowedTypes.includes(file.type)) {
    return {
      valid: false,
      message: '请上传正确格式的视频文件'
    };
  }

  const fileSize = (file.size / 1024 / 1024).toFixed(2);
  if (fileSize > maxSize) {
    return {
      valid: false,
      message: `文件大小不能超过${maxSize}MB`
    };
  }

  return { valid: true };
};

// 上传文件
export const uploadFile = async (file, fileCode, onProgress) => {
  try {
    // 获取文件MD5
    const md5 = await getFileMD5(file);

    // 获取七牛token
    const tokenResult = await qiniuTokenAPI({
      name: file.name,
      hash: md5
    });

    // 如果文件已存在,直接返回
    if (tokenResult.data) {
      onProgress?.(100);
      return tokenResult.data;
    }

    // 新文件上传
    if (tokenResult.token) {
      const suffix = getFileSuffix(file.name);
      const fileName = `uploadForm/${fileCode}/${md5}${suffix}`;

      // TODO: image_info 为七牛返回的图片信息,现在是上传视频看后期适配
      const { filekey, image_info } = await uploadToQiniu(
        file,
        tokenResult.token,
        fileName,
        onProgress
      );

      if (filekey) {
        // 保存文件信息
        const { data } = await saveFileAPI({
          name: file.name,
          filekey,
          hash: md5,
          height: image_info?.height,
          width: image_info?.width,
        });

        return data;
      }
    }

    throw new Error('上传失败');
  } catch (error) {
    console.error('Upload error:', error);
    throw error;
  }
};