h5压缩图片并上传到oss

需求背景:h5上传图片到oss,并返回图片的链接

参考资料:
阿里云oss
multipartUpload api
图片纯前端JS压缩的实现

注意:以下不包括业务代码,纯个人处理的oss上传封装,替换成自己的临时凭证的接口即可使用

const OSS = require('ali-oss');
/**
 *
 * @param {图片base64位地址} url
 * @returns
 */
const loadImage = function (url) {
  return new Promise((resolve, reject) => {
    let img = new Image();
    img.src = url;
    img.onload = () => resolve(img);
    img.onerror = reject;
  })
}
/**
 * 压缩图片、减少带宽
 * @param {*} file
 * @returns
 */
const compressImg = async function (file) {
  // 建立Canvas对象(画布)
  let canvas = document.createElement('canvas'),
    // 获取对应的CanvasRenderingContext2D对象(画笔)
    context = canvas.getContext('2d');
  let img = await loadImage(file.content);
  // 图片原始尺寸
  let originWidth = img.width,
    originHeight = img.height,
    // 最大尺寸限制
    maxWidth = 800, maxHeight = 800,
    // 目标尺寸
    targetWidth = originWidth, targetHeight = originHeight;
  // 图片尺寸超过500x500的限制
  if (originWidth > maxWidth || originHeight > maxHeight) {
    if (originWidth / originHeight > maxWidth / maxHeight) {
      // 更宽,按照宽度限定尺寸
      targetWidth = maxWidth;
      targetHeight = Math.round(maxWidth * (originHeight / originWidth));
    } else {
      targetHeight = maxHeight;
      targetWidth = Math.round(maxHeight * (originWidth / originHeight));
    }
  }
  // canvas对图片进行缩放
  canvas.width = targetWidth;
  canvas.height = targetHeight;
  // 清除画布
  context.clearRect(0, 0, targetWidth, targetHeight);
  // 图片压缩
  context.drawImage(img, 0, 0, targetWidth, targetHeight);
  return new Promise((resolve) => {
    canvas.toBlob((blob) => {
      resolve(blob)
    }, file.file.type || 'image/png');
  }).catch((err) => {
    console.log(err);
  })
}
/**
* 上传单张图片
* @param {Object} file 图片 类型为 File
* @param {} bucketType 存储类型
* @param {*} options
* @returns 图片的链接
*/
const uploadOneFile = async function (file, bucketType, options) {
  let suffix = file.file.name.slice(file.file.name.lastIndexOf('.') + 1), // 获取文件后缀
    param = {
      bucketType: bucketType, // 存储类型
      Suffix: suffix, // 文件后缀
      accessKey: '*******',
    }
  // 获取服务器临时访问权限. 从STS服务获取的临时访问凭证,临时访问凭证包括临时访问密钥(AccessKeyId和AccessKeySecret)和安全令牌(SecurityToken)。
  let res = await this.$httpRequest('你自己的URL', param); // 此处可换成你的Ajax请求,获取对应的凭证
  if (res.code !== 200) {
    console.log('获取阿里云OSS服务临时上传权限接口报错');
    throw new Error(res);
  }
  const { data } = res.data;
  const fileName = data.objectKey; // 后台生成的文件名
  const client = new OSS({
    region: 'oss-ap-southeast-1', // 申请OSS服务所在的地域
    endpoint: data.endpoint, // 访问域名
    accessKeyId: data.token.AccessKeyId, // 标识用户
    accessKeySecret: data.token.AccessKeySecret, // 用户用于加密签名字符串和OSS用来验证签名字符串的密钥
    bucket: data.bucket, // 存储空间
    stsToken: data.token.SecurityToken, // 安全令牌
    secure: true,
  });
  // 压缩图片
  let compressFile = await compressImg(file);

  return new Promise(async (resolve, reject) => {
    try {
      let res = await client.multipartUpload(fileName, compressFile, options);
      resolve(res.res.requestUrls[0].split('?')[0]);
    } catch (err) {
      console.log(err);
    }
  });
}

上传成功后:
在这里插入图片描述
图片的地址:文件名格式说明
在这里插入图片描述
例子:
以下例子是我使用上面的封装修改成H5的,可以使用云账号直接上传,一般我们都是使用请求接口获取临时权限才上传:
在这里插入图片描述
踩坑点:

  1. 2019.9月份后新建的bucket存储的图片,直接访问,会直接下载,如果想直接访问,有一种方式是配置域名,可能还有其他的。
  2. 使用服务去访问上传的图片,会被拒绝,直接浏览器就可以。
  3. 跨域配置,在bucket中配置, 刚开始设置,会有点延迟生效 _!!!,一直以为是我的问题 ,原来有点延迟,清一下缓存。
    在这里插入图片描述
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入oss的sdk -->
    <script src="http://gosspublic.alicdn.com/aliyun-oss-sdk-6.0.0.min.js"></script>
</head>

<body>
    <input id="file" type="file">
    <img src="" id="uploadImg">
</body>
<script>
    /**
     *
     * @param {图片地址} url
     * @returns
     */
    const loadImage = function (url) {
        return new Promise((resolve, reject) => {
            let img = new Image();
            img.src = url;
            img.onload = () => resolve(img);
            img.onerror = reject;
        })
    }
    /**
     * 压缩图片、减少带宽
     * @param {*} file
     * @returns
     */
    const compressImg = async function (file) {
        // 建立Canvas对象(画布)
        let canvas = document.createElement('canvas'),
            // 获取对应的CanvasRenderingContext2D对象(画笔)
            context = canvas.getContext('2d'),
            img = await loadImage(file.content),
            // 图片原始尺寸
            originWidth = img.width,
            originHeight = img.height,
            // 最大尺寸限制
            maxWidth = 800,
            maxHeight = 800,
            // 目标尺寸
            targetWidth = originWidth,
            targetHeight = originHeight;
        // 图片尺寸超过500x500的限制
        if (originWidth > maxWidth || originHeight > maxHeight) {
            if (originWidth / originHeight > maxWidth / maxHeight) {
                // 更宽,按照宽度限定尺寸
                targetWidth = maxWidth;
                targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            } else {
                targetHeight = maxHeight;
                targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            }
        }
        // canvas对图片进行缩放
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        // 清除画布
        context.clearRect(0, 0, targetWidth, targetHeight);
        // 图片压缩
        context.drawImage(img, 0, 0, targetWidth, targetHeight);
        return new Promise((resolve) => {
            canvas.toBlob((blob) => {
                resolve(blob)
            }, file.type || 'image/png');
        }).catch((err) => {
            console.log(err);
        })
    }

    /**
     * 上传单张图片
     * @param {Object} file
     * @param {} bucketType 存储类型
     * @param {*} options
     * @returns 图片链接
     */
    const uploadOneFile = async function (file, bucketType, options) {

        /** 
         * 1. 此处可以Ajax请求获取服务器临时访问权限. 从STS服务获取的临时访问凭证,临时访问凭证包括临时访问密钥
         * (AccessKeyId和AccessKeySecret)和安全令牌(SecurityToken)。
         * 2. 如果你有自己的服务器,也可以拿永久的来尝试看看,正常应该使用临时访问权限
         */
        const client = new OSS({
            region: '******', // 申请OSS服务所在的地域
            accessKeyId: '******', // 标识用户
            accessKeySecret: '*****', // 用户用于加密签名字符串和OSS用来验证签名字符串的密钥
            bucket: 'uploade', // 存储空间
            secure: true,
        });

        let compressFile = await compressImg(file);
        return new Promise(async (resolve, reject) => {
            try {
                let res = await client.multipartUpload(file.name, compressFile);
                resolve(res.res.requestUrls[0].split('?')[0]);
            } catch (err) {
                console.log(err);
            }
        });
    }
    const add = () => {
        let inputFile = document.getElementById("inputFile"),
            uploadImg = document.getElementById("uploadImg")
        eleFile = document.querySelector('#file'), reader = new FileReader();
        eleFile.addEventListener('change', (event) => {
            file = event.target.files[0];
            // 选择的文件是图片
            if (file.type.indexOf("image") == 0) {
                // 这里主要是从系统中获取上传的文件转成base64位,正常我们使用现成的ui库,如vant,是可以直接拿到base64位的图片地址
                reader.readAsDataURL(file);

                reader.onload = async (e) => {
                    file.content = e.target.result;
                    let res = await uploadOneFile(file);
                    uploadImg.src = res;
                    console.log(res);
                };
            }
        });
    }
    add();
</script>

</html>

尝试上传 85.6 KB的图片
在这里插入图片描述
浏览器:
使用服务访问:
在这里插入图片描述
直接访问:
在这里插入图片描述
oss客户端查看我上传的图片:可以看到图片被压缩了,变成了30.48kb
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值