使用腾讯云对象存储给halo中上传的图片添加水印

Tch
Tch
Published on 2025-03-12 / 83 Visits
0
1

1. 开通对象存储

只要支持S3协议的对象存储就行,我选的是腾讯云的对象存储COS,开通和配置过程就省略了,官方文档里都有。

https://console.cloud.tencent.com/cos

2. 安装插件

在应用市场安装插件对象存储(Amazon S3协议),只要使用的对象存储支持S3协议该插件都可以用。

安装完插件后,在附件里添加添加存储策略,按照官方的配置指南操作就行了。

https://github.com/halo-dev/plugin-s3

3. 新增水印样式

进入存储桶,选择对象存储 -> 数据处理 -> 图片处理 -> 基础图片处理,状态改为打开。

在页面下方,点击新增样式

样式分隔符默认是/ (斜杠),有需要可以修改。

输入一个样式名称,和别的样式作区分。

选择要加的样式,我选择文字水印图片水印组合的样式,有别的需要可以再加。

图片水印添加:

选择一个要作为水印的图片,要按照说明里的要求,不然水印加不上。

下面还有一些别的配置,根据自己的需求来就行。

文字水印添加:

选择一句话作为水印的文字内容,别的配置根据自己的需求来就行。

预览效果:

添加完水印的样式,点击预览效果就可以看到加的水印是什么样了。

把最下边的处理参数复制出来后边要用,点击保存水印样式就添加完了。

4. 图片添加水印

水印样式有了,怎么使用官方文档里也写了。

https://cloud.tencent.com/document/product/460/46823?from=console_document_search#.E6.A0.B7.E5.BC.8F.E7.AE.A1.E7.90.86

总结下来就是把上边生成的处理参数加到图片地址的后边就行了。

举个栗子就是👇

原图片地址:https://examplebucket-1250000000.cos.ap-chengdu.myqcloud.com/sample.jpeg

加水印地址:https://examplebucket-1250000000.cos.ap-chengdu.myqcloud.com/sample.jpeg?处理参数

接下来就好办了,打开附件库 -> 存储策略 -> 腾讯云对象存储策略 -> 编辑。

拉到最下边有个网址后缀,把?处理参数填进去,文件后缀根据实际填。

(这里有个注意的点,在水印样式的处理参数中,图片水印和文字水印的参数中间有个分隔符"|",必须替换成%7C

有个URI.create()的方法,参数部分存在非法字符上传图片时会出错。)

这样水印就添加成功了,上传一个图片试试。

可以看到水印添加成功了,下边的URL里也可以看到图片地址后边的处理参数。

5. 进一步探究

图片水印是加上了的,但是在腾讯云对象存储的存储桶里,上传的这张照片并没有水印。

在官网文档的图片处理机制介绍里写了有,在图片的地址后加处理参数的方式属于下载时处理,访问图片的时候同步获取到处理后的图片,所以附件库里的图片有水印了,存储桶里的原图还没有水印。

https://cloud.tencent.com/document/product/460/18147

如果想给存储桶里的图片也加上水印就要选择上传时处理了,不过插件里应该是使用的是下载时处理

我们来看看插件的代码,在上传成功后调用getPermalink方法,先根据对象的key生成永久链接,然后在获取URL后缀拼接在永久链接的后边,这个后缀就是前面在对象存储策略中设置的网址后缀。

@Override
    public Mono<URI> getPermalink(Attachment attachment, Policy policy, ConfigMap configMap) {
        if (!this.shouldHandle(policy)) {
            return Mono.empty();
        }
        // 获取附件的对象键
        var objectKey = getObjectKey(attachment);
        if (objectKey == null) {
            // 如果对象键为空,回退到默认处理器
            return Mono.empty();
        }
        // 将配置转换为 S3OsProperties
        var properties = S3OsProperties.convertFrom(configMap);
        // 生成对象的永久链接
        var objectURL = properties.toObjectURL(objectKey);
        // 获取 URL 后缀
        var urlSuffix = getUrlSuffixAnnotation(attachment);
        if (StringUtils.isNotBlank(urlSuffix)) {
            objectURL += urlSuffix;
        }
        return Mono.just(URI.create(objectURL));
    }
@Nullable
    private String getUrlSuffixAnnotation(Attachment attachment) {
        // 从附件的元数据中获取 URL 后缀
        var annotations = attachment.getMetadata().getAnnotations();
        if (annotations == null) {
            return null;
        }
        return annotations.get(URL_SUFFIX_ANNO_KEY);
    }

获取后缀时的URL_SUFFIX_ANNO_KEY和画面上的元素name是一致的。

6. 注意事项

在存储策略里加了后缀URL后,网页<img>标签的srcset属性里,参数imageView2前面的?会变成&,导致水印失效,无法正常显示。

暂时只能通过代码注入的方式,把&替换成?,看后续版本升级后能否解决。

<script>
// 解决图片水印不正常显示问题

// 监听DOM加载完成事件
document.addEventListener('DOMContentLoaded', function() {
  // 获取所有<img>标签
  const images = document.getElementsByTagName('img');
  
  // 遍历所有图片
  Array.from(images).forEach(img => {
    // 检查是否存在srcset属性
    if (img.hasAttribute('srcset')) {
      // 获取原始srcset值
      let srcset = img.getAttribute('srcset');
      
      // 执行字符串替换(注意转义问题)
      const newSrcset = srcset.replace(/&imageView2/g, '?imageView2');
      
      // 更新srcset属性
      img.setAttribute('srcset', newSrcset);
    }
  });
});
</script>

以上。


Comment