阿里云 OSS

通过文件访问 URL 处理图片

您可以在图片的访问 URL 后添加相应的图片处理参数或图片样式处理图片,格式如下: 使用图片处理参数

使用样式参数

示例:http://image-demo.oss-cn-hangzhou.aliyuncs.com/examplejpg?x-oss-process=style/panda_style

若您设置了自定义分隔符,可使用分隔符代替?x-oss-process=style/内容,进一步简化图片处理 URL。例如分隔符设置为感叹号(!),则图片处理 URL 为:<https://bucketname.endpoint/objectname!stylename。自定义分隔符的配置方式请参见设置自定义分隔符。

参数

图片处理 参数 说明
图片高级压缩 format 将图片转换为 HEIF 或 WebP M6 等高压缩比格式。
图片缩放 resize 将图片缩放至指定大小。
内切圆 circle 以图片中心点为圆心,裁剪出指定大小的圆形图片。
自定义裁剪 crop 裁剪指定大小的矩形图片。
索引切割 indexcrop 按指定 x 或 y 轴的大小切分图片,之后取其中一张图片。
圆角矩形 rounded-corners 按指定圆角大小将图片裁剪成圆角矩形。
自适应方向 auto-orient 将携带旋转参数的图片进行自适应旋转。
旋转 rotate 按指定角度以顺时针方向旋转图片。
模糊效果 blur 对图片进行模糊处理。
亮度 bright 调整图片亮度。
锐化 sharpen 对图片进行锐化处理。
对比度 contrast 调整图片对比度。
渐进显示 interlace 将 JPG 格式的图片调整为渐进显示。
质量变换 quality 调整 JPG 和 WebP 格式图片的质量。
格式转换 format 转换图片格式。
图片水印 watermark 为图片添加图片或文字水印。
获取图片主色调 average-hue 获取图片主色调。
获取信息 info 获取图片信息,包括基本信息、EXIF 信息。

$process

import Vue from 'vue'
/**
 * 浏览器是否支持webp
 * @type {boolean}
 */
let webpSupported = false

const ResizeImage = {
    /**
     * 注册图片处理的全局方法 $process
     * @param {object} _Vue vue
     */
    install(_Vue) {
        /**
         * 为图片url添加缩放、格式转换等请求参数
         * https://help.aliyun.com/document_detail/44686.html?spm=a2c4g.11186623.6.1235.61a5c1f60U7rVj
         * @param {string} url 图片链接
         * @param {object} params 参数
         * @param {string} [params.style] 预定义参数
         * @param {number} [params.width] 等比例缩放宽度
         * @param {boolean} [params.matchScreen=false] 默认false,图片宽度匹配屏幕分辨率,但最大不会超过1980
         * @param {boolean} [params.webp=true] 图片转换为webp,默认true
         * @return {string} 处理后的图片链接
         */
        _Vue.prototype.$process = (url, params = {}) => {
            if (!url) {
                return url
            }

            // 判断图片格式是否支持,不支持则返回原链接,不进行处理
            if (!_support(url)) {
                return url
            }

            if (url.indexOf('forucdn.com') === -1) {
                return url
            }

            url = _modifyUrl(url)

            const cmd = [
                url,
                // 默认增加渐进显示图片设置(interlace,1),由oss 自己判断是否渐进显示图片
                // 渐进显示图片,只对jpg格式有效
                (_getQuery(url) ? '&' : '?') + 'x-oss-process=image/interlace,1'
            ]

            // 预定义尺寸
            if (params.style) {
                cmd.push(params.style)
            }

            // 图片宽度匹配屏幕分辨率,但最大不会超过1980
            if (params.matchScreen) {
                const width = Math.min(screen.width, 1980)
                cmd.push(`/resize,w_${width}`)
            }

            // 等比例缩放
            if (params.width) {
                cmd.push(`/resize,w_${params.width}`)
            }

            // 转换为webp格式,默认不使用
            params.webp = params.webp === undefined ? false : params.webp
            // 由于效果图提升了图片质量,图片大小增加,使用webp图片格式来减小图片大小
            // assets.forucdn.com 图片也使用webp
            if (webpSupported && (params.webp || url.indexOf('samples.forucdn.com') !== -1 || url.indexOf('assets.forucdn.com') !== -1)) {
                cmd.push('/format,webp')
            }

            // 当浏览器不支持webp图片时图片使用jpeg格式
            if (!webpSupported) {
                cmd.push('/format,jpg')
            }

            return cmd.join('')
        }
    }
}

/**
 * 获取图片参数
 * @param {string} url 图片链接
 * @return {string} 图片后缀
 */
const _getQuery = (url) => {
    if (url.indexOf('?') === -1) return ''
    return url.slice(url.indexOf('?'))
}

/**
 * 判断是否支持该图片类型
 * @param {string} url 图片链接
 * @return {boolean} 是否支持
 */
const _support = (url) => {
    const reg = /\.(jpg|jpeg|png|bmp|gif|webp|tif|tiff)$/
    return reg.test(url.replace(_getQuery(url), ''))
}

/**
 * 如果图片类型为原图,需要修改为缩略图的链接
 * @param {string} url 图片链接
 * @returns {string} 修改后的图片链接
 * @private
 */
const _modifyUrl = (url) => {
    // 移除预定义样式
    // @todo 待后台不再传该值时可以移除
    url = url.replace(/\!index_slider|\!index_artists_avatar|\!index_collections/, '')

    if (!url.match('galleries')) {
        return url
    }

    const char_index = url.lastIndexOf('.')
    return url.slice(0, char_index) + '-thumb' + url.slice(char_index)
}

/**
 * 检测客户端是否支持webp
 * @returns {boolean} 是否支持
 */
const _clientSideDetectionForWebp = () => {
    return new Promise((resolve) => {
        const image = new Image()
        image.onerror = () => resolve(false)
        image.onload = () => resolve(true)
        image.src = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA='

        // // If the browser doesn't has the method createImageBitmap, you can't display webp format
        // if(!window.createImageBitmap){
        //     return resolve(false)
        // }

        // // Base64 representation of a white point image
        // const webpdata = 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoCAAEAAQAcJaQAA3AA/v3AgAA='

        // // Retrieve the Image in Blob Format
        // fetch(webpdata).then((response) => response.blob())
        //     .then((blob) => {
        //         // If the createImageBitmap method succeeds, return true, otherwise false
        //         window.createImageBitmap(blob).then(() => resolve(true), () => resolve(false))
        //     })
    })
}

/**
 * 服务端检测是否支持webp
 * @param {object} ctx nuxt ctx
 * @returns {boolean} 是否支持
 * @private
 */
const _serverSideDetectionForWebp = (ctx) => {
    const headers = ctx.req.headers
    return _detectByAccept(headers.accept) || _detectByUserAgent(headers['user-agent'])
}

/**
 * 通过headers头中的accept字段判断是否支持webp
 * @param {string|undefined} accept accept字段值
 * @returns {boolean} 结果
 * @private
 */
const _detectByAccept = (accept) => {
    return accept && null !== accept.match('image/webp')
}

/**
 * 通过headers头中的user-agent字段判断是否支持webp
 * @param {string|undefined} user_agent user-agent字段值
 * @returns {boolean} 结果
 * @private
 */
const _detectByUserAgent = (user_agent) => {
    return user_agent && null !== user_agent.match(/Opera|Chrome|Firefox/)
}

export default async () => {
    webpSupported = process.server ? false : await _clientSideDetectionForWebp()

    Vue.use(ResizeImage)
}