溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何用Serverless給網(wǎng)站圖片加水印

發(fā)布時(shí)間:2021-07-29 22:01:55 來源:億速云 閱讀:127 作者:chen 欄目:云計(jì)算

這篇文章主要介紹“如何用Serverless給網(wǎng)站圖片加水印”,在日常操作中,相信很多人在如何用Serverless給網(wǎng)站圖片加水印問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”如何用Serverless給網(wǎng)站圖片加水印”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!


傳統(tǒng)的加水印的方法,通常是在流程內(nèi)進(jìn)行。即:

如何用Serverless給網(wǎng)站圖片加水印

這種做法雖然可行,但是無疑會(huì)增加單次請(qǐng)求,服務(wù)端的壓力,如果是高并發(fā)的情況下,或者多人上傳多張大圖的時(shí)候,那么可能就會(huì)造成自身服務(wù)器資源效果過大。

如果在加水印過程中失敗,就有可能導(dǎo)致圖像存儲(chǔ)失敗,致使數(shù)據(jù)丟失,并不理智。所以后來有人做了如下改進(jìn):

如何用Serverless給網(wǎng)站圖片加水印

這樣做法的好處就是 —— 我們可以快速將圖片存儲(chǔ),存儲(chǔ)之后通過一個(gè)單獨(dú)處理的線程,對(duì)任務(wù)列表進(jìn)行處理,這樣一方面是可以保證我們馬上把用戶上傳的圖片存儲(chǔ),并且可以顯示,同時(shí)也可以在后臺(tái)進(jìn)行水印處理,待處理之后,再將圖片覆蓋或者單獨(dú)存儲(chǔ),用戶如果需要讀取圖片時(shí),可以自動(dòng)變?yōu)橐呀?jīng)水印后的圖片。

這種做法相對(duì)于前者來說可能稍微復(fù)雜一些,但是實(shí)際上卻是在數(shù)據(jù)上更加穩(wěn)定,服務(wù)端壓力更小,更加可控的一種操作。但是,這整個(gè)流程還是要在自己的服務(wù)器上做完,現(xiàn)在已經(jīng)有很多人將圖片等資源存儲(chǔ)到騰訊云的 對(duì)象存儲(chǔ)(COS)中,那么可不可以通過某些 COS 觸發(fā)器與云函數(shù) SCF 結(jié)合,實(shí)現(xiàn)一個(gè)不在自己服務(wù)器加水印的流程呢?

本文將以騰訊云函數(shù) SCF 的函數(shù)模板(Python 語言)為例,進(jìn)行一個(gè)簡單的分享。

▎實(shí)驗(yàn)

新建函數(shù)

在無服務(wù)器云函數(shù)中,選擇模板函數(shù):

如何用Serverless給網(wǎng)站圖片加水印

通過搜索「圖像」關(guān)鍵詞,選中圖像壓縮,并且確定建立。保存之后,點(diǎn)擊函數(shù)代碼,進(jìn)行代碼編寫。

如何用Serverless給網(wǎng)站圖片加水印

COS 觸發(fā)器

有些人可能對(duì) COS 觸發(fā)器還不是很了解,此時(shí)可以點(diǎn)擊配置,來熟悉 COS 觸發(fā)器樣式:

如何用Serverless給網(wǎng)站圖片加水印

可以看到如下:

{
   "Records":[
      {
        "event": {
          "eventVersion":"1.0",
          "eventSource":"qcs::cos",
          "eventName":"cos: ObjectCreated: *",
          "eventTime":1501054710,
          "eventQueue":"qcs:0:cos:gz:1251111111:cos",
          "requestParameters":{
            "requestSourceIP": "111.111.111.111",
            "requestHeaders":{
              "Authorization": "上傳的鑒權(quán)信息"
            }
          }
         },
         "cos":{
            "cosSchemaVersion":"1.0",
            "cosNotificationId":"設(shè)置的或返回的 ID",
            "cosBucket":{
               "name":"bucketname",
               "appid":"appId",
               "region":"gz"
            },
            "cosObject":{
               "key":"/appid/bucketname/DSC_0002.JPG",
               "size":2598526,
               "meta":{
                 "Content-Type": "text/plain",
                 "x-cos-meta-test": "自定義的 meta",
                 "x-image-test": "自定義的 meta"
               },
               "url": "訪問文件的源站url"
            }
         }
      }
   ]
}

這里面可以看到整個(gè)一個(gè)數(shù)據(jù)結(jié)構(gòu),需要注意 Records 是一個(gè)數(shù)組格式,其次就是:

"cosBucket":{"name":"bucketname","appid":"appId","region":"gz"}

這里面是由該 bucket 觸發(fā)

"cosObject":{"key":"/appid/bucketname/DSC_0002.JPG","size":2598526,"meta":{"Content-Type":"text/plain","x-cos-meta-test":"自定義的 meta","x-image-test":"自定義的 meta"},"url":"訪問文件的源站 url"}

這里面的 key 是在上述 bucket 中新建的文件名字。

所以,我們可以按照我們的實(shí)際情況,將上面的內(nèi)容簡單修改一下,成為我們格式,以便測試(在生產(chǎn)中,這個(gè)是自動(dòng)生成的觸發(fā)格式,并不需要我們修改,我們修改只是為了測試.

{
   "Records":[
      {
        "event": {
          "eventVersion":"1.0",
          "eventSource":"qcs::cos",
          "eventName":"cos: ObjectCreated: *",
          "eventTime":1501054710,
          "eventQueue":"qcs:0:cos:gz:1251111111:cos",
          "requestParameters":{
            "requestSourceIP": "111.111.111.111",
            "requestHeaders":{
              "Authorization": "上傳的鑒權(quán)信息"
            }
          }
         },
         "cos":{
            "cosSchemaVersion":"1.0",
            "cosNotificationId":"設(shè)置的或返回的 ID",
            "cosBucket":{
               "name":"mytestcos",
               "appid":"appId",
               "region":"gz"
            },
            "cosObject":{
               "key":"test.png",
               "size":2598526,
               "meta":{
                 "Content-Type": "text/plain",
                 "x-cos-meta-test": "自定義的 meta",
                 "x-image-test": "自定義的 meta"
               },
               "url": "訪問文件的源站url"
            }
         }
      }
   ]
}

這里主要修改了我的 cosBucket-name: mytestcos,以及 key: test.png

如何用Serverless給網(wǎng)站圖片加水印

代碼修改

之所以使用現(xiàn)有的模板,是因?yàn)樵撃0宓挠?PIL 和 qcloud_cos_v5 等相關(guān) package,而這兩個(gè) package 正是我們即將需要的,這樣就可以省去我們打包函數(shù)的流程,只需要進(jìn)行簡單修改即可實(shí)現(xiàn)。

添加水?。?/p>

def add_word(pic_path, save_path):
    # 打開圖片
    im = Image.open(pic_path).convert('RGBA')
    # 新建一個(gè)空白圖片,尺寸與打開圖片一樣
    txt = Image.new('RGBA', im.size, (0, 0, 0, 0))
    # 設(shè)置字體
    fnt = ImageFont.truetype("/tmp/font.ttf", 40)
    # 操作新建的空白圖片>>將新建的圖片添入畫板
    d = ImageDraw.Draw(txt)
    # 在新建的圖片上添加字體
    d.text((txt.size[0] - 220, txt.size[1] - 80), "By Dfounder", font=fnt,  fill=(255, 255, 255, 255))
    # 合并兩個(gè)圖片
    out = Image.alpha_composite(im, txt)
    # 保存圖像
    out.save(save_path)

在添加水印的時(shí)候,我們?cè)O(shè)置的是文字水印,所以需要設(shè)置字體和字號(hào):

fnt = ImageFont.truetype("/tmp/font.ttf",40)

此時(shí),我們需要在執(zhí)行之前,先將字體文件傳入到 /tmp/ 文件夾下:

response = client.get_object(Bucket="mytestcos-12567****", Key="font.ttf", ) response['Body'].get_stream_to_file('/tmp/font.ttf')

以我的 cos 為例:

如何用Serverless給網(wǎng)站圖片加水印

然后,接下來就是對(duì)觸發(fā)的 event 進(jìn)行解析,包括獲得新建的圖像名稱,從 COS 拉取,放到本地,然后進(jìn)行水印等,再上傳回新的 COS 中:

for record in event['Records']:
        try:
            bucket = record['cos']['cosBucket']['name'] + '-' + str(appid)
            key = record['cos']['cosObject']['key']
            key = key.replace('/' + str(appid) + '/' + record['cos']['cosBucket']['name'] + '/', '', 1)
            download_path = '/tmp/{}'.format(key)
            upload_path = '/tmp/new_pic-{}'.format(key)

            # 下載圖片
            try:
                response = client.get_object(Bucket=bucket, Key=key, )
                response['Body'].get_stream_to_file(download_path)
            except CosServiceError as e:
                print(e.get_error_code())
                print(e.get_error_msg())
                print(e.get_resource_location())

            # 圖像增加水印
            add_word(download_path, upload_path)


            # 圖像上傳
            response = client.put_object_from_local_file(
                Bucket=to_bucket,
                LocalFilePath=upload_path.decode('utf-8'),
                Key=("upload-" + key).decode('utf-8')
            )

        except Exception as e:
            print(e)

此處說明一下,為什么要有兩個(gè)存儲(chǔ)桶?

因?yàn)槲覀円岩粋€(gè)存儲(chǔ)桶作為觸發(fā) SCF 函數(shù)的「工具」,如果我們將水印結(jié)果再次寫回這個(gè)存儲(chǔ)桶,在不進(jìn)行額外判斷和處理的前提下,那么這個(gè)水印后的圖片會(huì)再次水印,反反復(fù)復(fù)造成惡劣的循環(huán),所以此處建立兩個(gè)存儲(chǔ)桶,可以降低難度,也可以保護(hù)性能,減少 BUG 誕生。

完整代碼如下:

# -*- coding: utf-8 -*-

from PIL import Image, ImageFont, ImageDraw
from qcloud_cos_v5 import CosConfig
from qcloud_cos_v5 import CosS3Client
from qcloud_cos_v5 import CosServiceError
from qcloud_cos_v5 import CosClientError

appid = **  # 請(qǐng)?zhí)鎿Q為您的 APPID
secret_id = ***'  # 請(qǐng)?zhí)鎿Q為您的 SecretId
secret_key = **'  # 請(qǐng)?zhí)鎿Q為您的 SecretKey
region = u'ap-chengdu'  # 請(qǐng)?zhí)鎿Q為您bucket 所在的地域
token = ''
to_bucket = 'tobucket-12567***'  # 請(qǐng)?zhí)鎿Q為您用于存放壓縮后圖片的bucket

config = CosConfig(Secret_id=secret_id, Secret_key=secret_key, Region=region, Token=token)
client = CosS3Client(config)

response = client.get_object(Bucket="mytestcos-12567***", Key="font.ttf", )
response['Body'].get_stream_to_file('/tmp/font.ttf')

def add_word(pic_path, save_path):
    # 打開圖片
    im = Image.open(pic_path).convert('RGBA')
    # 新建一個(gè)空白圖片,尺寸與打開圖片一樣
    txt = Image.new('RGBA', im.size, (0, 0, 0, 0))
    # 設(shè)置字體
    fnt = ImageFont.truetype("/tmp/font.ttf", 40)
    # 操作新建的空白圖片>>將新建的圖片添入畫板
    d = ImageDraw.Draw(txt)
    # 在新建的圖片上添加字體
    d.text((txt.size[0] - 220, txt.size[1] - 80), "By Dfounder", font=fnt,  fill=(255, 255, 255, 255))
    # 合并兩個(gè)圖片
    out = Image.alpha_composite(im, txt)
    # 保存圖像
    out.save(save_path)

def main_handler(event, context):
    for record in event['Records']:
        try:
            bucket = record['cos']['cosBucket']['name'] + '-' + str(appid)
            key = record['cos']['cosObject']['key']
            key = key.replace('/' + str(appid) + '/' + record['cos']['cosBucket']['name'] + '/', '', 1)
            download_path = '/tmp/{}'.format(key)
            upload_path = '/tmp/new_pic-{}'.format(key)

            # 下載圖片
            try:
                response = client.get_object(Bucket=bucket, Key=key, )
                response['Body'].get_stream_to_file(download_path)
            except CosServiceError as e:
                print(e.get_error_code())
                print(e.get_error_msg())
                print(e.get_resource_location())

            # 圖像增加水印
            add_word(download_path, upload_path)


            # 圖像上傳
            response = client.put_object_from_local_file(
                Bucket=to_bucket,
                LocalFilePath=upload_path.decode('utf-8'),
                Key=("upload-" + key).decode('utf-8')
            )

        except Exception as e:
            print(e)

這里面需要注意這幾個(gè)參數(shù):appid、secret_id、secret_key、to_bucket

這幾個(gè)參數(shù)的來源如下:

如何用Serverless給網(wǎng)站圖片加水印

而 secretid,secretkey 則需要在這里獲?。?/p>

如何用Serverless給網(wǎng)站圖片加水印

測試

之前我已經(jīng)上傳了一個(gè)測試圖片在這個(gè) bucket 中,名字是:test.png

如何用Serverless給網(wǎng)站圖片加水印

圖片是這樣子:

如何用Serverless給網(wǎng)站圖片加水印

然后我們進(jìn)行一下測試:

如何用Serverless給網(wǎng)站圖片加水印

可以看到,已經(jīng)測試成功,接下來我們可以去我們的目標(biāo) bucket 中看看:

如何用Serverless給網(wǎng)站圖片加水印

可以看到成功生成了一個(gè)圖片:

如何用Serverless給網(wǎng)站圖片加水印

可以看到圖片的右下角,有我們代碼中添加的水?。?/p>

如何用Serverless給網(wǎng)站圖片加水印

到此,關(guān)于“如何用Serverless給網(wǎng)站圖片加水印”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI