你只需要使用下面recursionCompress 这个方法就好了、
 import { recursionCompress } from '@/libs/tools';
 recursionCompress(data , type, false).then(({base64,blobData}) => {
       // 你的业务逻辑
});
 提供ts和js版本、开发者可根据自己的版本来选择
 第一个js版本 第二个ts版本。
 data : 数据源 ( blob| base64)
 status(boolean): 是否是uni的环境  默认不是
 返回值包括压缩之后的 base64 和 blob流
 使用者需要注意: blob 不能直接 img.src = blob 
 需要你转换一下URL.createObjectURL(blob) 这样才可以在图片上面显示
 uni 中是没有img这个标签的,所以需要 new Image()创建
 如果是app或者小程序 uni 提供uni.compressImage这方法了就不需要自己手写
 为了让调用者直观感受 图片是否被压缩 提供 imageSize() 计算base64图片大小
 因blob流本身具有size属性、所以不提供检查blob大小的方法
// base64转换为blob
 const dataUrlToBlob = (base64) => {
  let bytes = window.atob(base64.split(',')[1]);
  let ab = new ArrayBuffer(bytes.length);
  let ia = new Uint8Array(ab);
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], {type: 'image/jpeg'});
};

// blob转base64
 export const blobToBase64 = (blob) => {
  return new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.onload = (e) => {
      resolve(e.target.result);
    };
    fileReader.readAsDataURL(blob);
    fileReader.onerror = () => {
      reject(new Error('blobToBase64 error'));
    };
  });
};

// base64计算图片大小
export const imageSize = (base64Str) => {
  const indexBase64 = base64Str.indexOf('base64,');
  if (indexBase64 < 0) return -1;
  const str = base64Str.substr(indexBase64 + 6);
  return (str.length * 0.75).toFixed(2);
};

// 图片压缩逻辑
 const recursionCompressH5 = (blobUrl, quality, status) => {
  let canvas = document.createElement('canvas');
  return new Promise((resolve) => {
    let blob, img;
    // 如果不是uni 就正常创建
    if (!status) {
      img = document.createElement('img');
      blob = URL.createObjectURL(blobUrl);
    } else {
      // uni的情况
      img = new Image();
      blob = URL.createObjectURL(blobUrl);
    }
    img.src = blob;
    img.onload = () => {
      let screenWidth = img.width;
      let screenHeight = img.height;
      canvas.width = screenWidth;
      canvas.height = screenHeight;
      let ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
      let imageData = canvas.toDataURL('image/jpeg', quality);
      resolve(imageData);
    };
  });
};
/*
*   data : 数据源
*   status : 是否是uni的环境  默认不是
* */
export const recursionCompress = (data, status = false) => {
  return new Promise(async (resolve) => {
    if (typeof data === 'string') {
      const result = await handlerBase64(data, status);
     resolve(result);
      // 处理base64
    } else if (typeof data === 'object') {
      const result = await handlerBlob(data, status);
      resolve(result);
    }
  });
};
// 处理base64
const handlerBase64 = (data, status) => {
  return new Promise(async (resolve) => {
    // 如果是base64先转换为blob
    const blob = dataUrlToBlob(data);
    // 计算大小
    const quality = checkMagnification(blob.size);
    // 压缩之后的base64
   const base64 = await recursionCompressH5(blob, quality, status);
    // 压缩之后的blob
    const blobData = dataUrlToBlob(base64);
    resolve(
        {
          base64,
          blobData
        }
    );
  });
};
// 处理blob
const handlerBlob = (data, status) => {
  return new Promise(async (resolve) => {
    // 处理blob
    const quality = checkMagnification(data.size);
    // 压缩之后的base64
    const base64 = await recursionCompressH5(data, quality, status);
    // 压缩之后的blob
    const blobData = dataUrlToBlob(base64);
    resolve(
        {
          base64,
          blobData
        }
    );
  });
};
const checkMagnification = (size) => {
  let resultSize = size / 1024 / 1024;
  let quality = 1;
  if (resultSize > 0 && resultSize <= 0.8) {
    quality = 0.5;
  } else if (resultSize >= 1 && resultSize <= 2) {
    quality = 0.35;
  } else if (resultSize > 2 && resultSize <= 8) {
    quality = 0.2;
  } else if (resultSize > 8) {
    quality = 0.1;
  }
  return quality;
};

ts版本

// base64转换为blob
const dataUrlToBlob = (base64: string) => {
    let bytes = window.atob(base64.split(',')[1]);
    let ab = new ArrayBuffer(bytes.length);
    let ia = new Uint8Array(ab);
    for (let i = 0; i < bytes.length; i++) {
        ia[i] = bytes.charCodeAt(i);
    }
    return new Blob([ab], {type: 'image/jpeg'});
};
// blob转base64
export const blobToBase64 = (blob: Blob) => {
    return new Promise((resolve, reject) => {
        const fileReader = new FileReader();
        fileReader.onload = (e) => {
            resolve(e.target?.result);
        };
        fileReader.readAsDataURL(blob);
        fileReader.onerror = () => {
            reject(new Error('blobToBase64 error'));
        };
    });
};
// base64计算图片大小
export const imageSize = (base64Str: string) => {
    const indexBase64 = base64Str.indexOf('base64,');
    if (indexBase64 < 0) return -1;
    const str = base64Str.substr(indexBase64 + 6);
    return (str.length * 0.75).toFixed(2);
};
// 图片压缩逻辑
const recursionCompressH5 = (blobUrl: Blob, quality: number, status: boolean): Promise<string> => {
    let canvas = document.createElement('canvas');
    return new Promise((resolve) => {
        let blob, img: HTMLImageElement;
        // 如果不是uni 就正常创建
        if (!status) {
            img = document.createElement('img');
            blob = URL.createObjectURL(blobUrl);
        } else {
            // uni的情况
            img = new Image();
            blob = URL.createObjectURL(blobUrl);
        }
        img.src = blob;
        img.onload = () => {
            let screenWidth = img.width;
            let screenHeight = img.height;
            canvas.width = screenWidth;
            canvas.height = screenHeight;
            let ctx = canvas.getContext('2d');
            ctx?.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
            ctx?.drawImage(img, 0, 0, canvas.width, canvas.height);
            // 这里image/jpeg不可修改
            let imageData = canvas.toDataURL('image/jpeg', quality);
            resolve(imageData);
        };
    });
};
/*
*   data : 数据源
*   status : 是否是uni的环境  默认不是
* */
export const recursionCompress = (data: Blob | string, status = false): Promise<{ base64: string, blobData: Blob }> => {
    return new Promise(async (resolve) => {
        if (typeof data === 'string') {
            const result = await handlerBase64(data, status);
            resolve(result);
            // 处理base64
        } else if (typeof data === 'object') {
            const result = await handlerBlob(data, status);
            resolve(result);
        }
    });
};
// 处理blob
const handlerBlob = (data: Blob, status: boolean): Promise<{ base64: string, blobData: Blob }> => {
    return new Promise(async (resolve) => {
        // 处理blob
        const quality = checkMagnification(data.size);
        // 压缩之后的base64
        const base64 = await recursionCompressH5(data, quality, status);
        // 压缩之后的blob
        const blobData = dataUrlToBlob(base64);
        resolve(
            {
                base64,
                blobData
            }
        );
    })
}
// 处理base64
const handlerBase64 = (data: string, status: boolean): Promise<{ base64: string, blobData: Blob }> => {
    return new Promise(async (resolve) => {
        // 如果是base64先转换为blob
        const blob = dataUrlToBlob(data);
        // 计算大小
        const quality = checkMagnification(blob.size);
        // 压缩之后的base64
        const base64 = await recursionCompressH5(blob, quality, status);
        // 压缩之后的blob
        const blobData = dataUrlToBlob(base64);
        resolve(
            {
                base64,
                blobData
            }
        )
    })
}
// 压缩比重
const checkMagnification = (size: number) => {
    let resultSize = size / 1024 / 1024;
    let quality = 1;
    if (resultSize > 0 && resultSize <= 0.8) {
        quality = 0.5;
    } else if (resultSize >= 1 && resultSize <= 2) {
        quality = 0.35;
    } else if (resultSize > 2 && resultSize <= 8) {
        quality = 0.2;
    } else if (resultSize > 8) {
        quality = 0.1;
    }
    return quality;
};
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐