iT邦幫忙

2023 iThome 鐵人賽

DAY 17
1
SideProject30

營養師不開菜單要用 Next.js 13 寫全端系列 第 17

營養師不開菜單的第十七天 - 在 Next.js 中使用 Cloudinary CDN 管理媒體資源

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20230930/20152073fRktJ6BTp8.png

Cloudinary 是一個雲端媒體管理平台,主要提供需要大量處理及優化圖片及影片的開發者管理及優化服務,可以藉由平台上傳、儲存及管理資源,並且讓媒體資源在不同的裝置和環境下皆可以最佳化。除此之外 Cloudinary 也提供 Image CDN 服務,確保全球各地的用戶都能迅速且高效地取得所需的圖片或影片。就像碳水化合物的分解作用,人體攝取之後經過分解為小分子的葡萄糖,可以儲存在肌肉或是肝臟,等待有需要時可以釋出提供能量。

在自建的資料庫管理媒體資料?


如果在自己建立的資料庫儲存及管理媒體資料,雖然可以有很大的操控權,但相對的也需要付出更多維護及管理成本,例如:

  1. 儲存成本:影片和圖片的大小及格式非常多樣,所以大小也可能因為解析度及或影片長度而到幾G的容量,必須確保有足夠的儲存空間及擴展的可能性。
  2. 轉碼和優化:如果存儲影片,可能需要轉碼服務以適應不同的設備和 bandwidth。對於圖片,也需要自行使用工具進行壓縮和優化,以加速載入速度。
  3. 備份與恢復:大量的媒體資料可能使備份和恢復變得更加複雜和耗時。
  4. 效能問題:直接從資料庫提供媒體資料可能導致資料庫的讀取速度受到影響,也可能會對應用程式其他功能造成延遲。
  5. 流量成本:如果有大量使用者訪問這些媒體資料,流量的消耗速度可能會很快,所以需要優化資料和分散和管理流量壓力。

為什麼要使用 Cloudinary?


基於上面所敘述的在自建的資料庫中處理媒體資料需要非常多額外的成本,但是本專案不論是金錢或是時間成本都是秉持越低越好,所以希望可以藉由現成的雲端服務對圖片進行管理及優化:

  1. 自動優化:Cloudinary 可以自動調整和優化圖片和影片,以確保最佳的質量和最小的檔案大小。
  2. 節省存儲空間:透過動態轉換,只需要儲存原始檔案,然後可以按需生成各種版本。
  3. 內建 CDN:Cloudinary 內鍵 CDN,使這些媒體資料可以被快速地傳遞到全球的用戶。
  4. 即時轉換:Cloudinary 可以在上傳時即時進行圖像和視頻轉換,包括裁剪、縮放、格式轉換、特效等等。
  5. 友善開發:提供多元的 API 和 SDK,支援各式程式語言跟框架,友善整合到已存在的應用程式中。
  6. 提供上傳 UI 介面:除了由本地上傳資料也可以藉由網址、雲端、社群網站或其他圖片收集網站中上傳圖片。
  7. 提供免費額度:以目前的 side project 規模,使用服務提供的免費額度已經綽綽有餘,省時又省錢。
    • 每月 25,000 個資源轉換額度:例如裁剪、縮放、特效添加等
    • 25GB 管理儲存空間
    • 每月 25GB 網路觀看頻寬:每月用戶從 Cloudinary 下載或觀看媒體檔案所使用的總頻寬

https://ithelp.ithome.com.tw/upload/images/20230930/20152073T8T3oWEZOl.png

在專案中設置


想要在專案中使用,首先必須註冊 Cloudinary 的帳號,再藉由 Cloudinary 支持的 Next.js 服務套件 next-cloudinary 進行設置,接下來就先從註冊開始吧!

註冊 Cloudinary

註冊網址:https://cloudinary.com/users/register_free?utm_campaign=devx_nextcloudinary&utm_medium=referral&utm_source=nextcloudinary

https://ithelp.ithome.com.tw/upload/images/20230930/20152073PsBQpmigQa.png

選擇角色

選擇 Developer 使用 API 與 SDK

https://ithelp.ithome.com.tw/upload/images/20230930/20152073honiJbNfYW.png

註冊成功畫面

選擇 Developer 註冊成功後會顯示具有 SDK 及API 的畫面

https://ithelp.ithome.com.tw/upload/images/20230930/20152073TNdRsaqM3u.png

如果是選擇 marketing / creative 則會進入 Cloudinary 的後台管理 Digital Asset Management

但可以藉由左側的選項切換介面不用擔心!

https://ithelp.ithome.com.tw/upload/images/20230930/2015207308bx1J1bH5.png

安裝 next-cloudinary

註冊完 Cloudinary 後暫時先回到專案中安裝專為 Next.js 設計的套件 next-cloudinary 再進行金鑰設定

安裝

npm install next-cloudinary

取得 cloud name

安裝 next-cloudinary 後,需要在環境變數中設定 Cloudinary 的 cloud name 作為金鑰才可以使用服務,回到 Cloudinary 的 Dashboard 頁面,在 cloud name 區塊取得金鑰

https://ithelp.ithome.com.tw/upload/images/20230930/20152073Ow4klSHXac.png

環境變數設置

將取得的金鑰設置於環境變數

NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="<Your Cloud Name>"

實作上傳區域

next-cloudinary 為使用者省去了許多建置 cloudinary 的設定,在設定環境變數後就可以直接使用套件提供的元件進行開發

提供的元件

  1. <CldImage/>: 可以從 Cloudinary 取得圖片並在 Next.js 中使用
  2. <CldOgImage/>:使用與 CldImage 相同的 API 在 Next.js 中生成 Open Graph 圖片
  3. <CldUploadButton/>:會建立一個按鈕元件,並且點擊這個按鈕可以顯示 Cloudinary 提供的 Upload Widget
  4. <CldUploadWidget/>:直接建立一個 new Cloudinary Upload Widget,上傳的元件介面
  5. <CldVideoPlayer/>:透過 Cloudinary Video Player 嵌入 Cloudinary 中的影片,也可以為播放器的操控元件做客製化設定。

實作說明

在本次專案中使用的元件是 <CldUploadWidget/>,並搭配主題中的 Button 元件後進行圖片上傳功能

<CldUploadWidget>
  {({ cloudinary, widget, open }) => {
    // Button 元件
  }}
</CldUploadWidget>

實作 ImageUpload 元件

元件中回傳的 function 除了 cloudinary、widget、open 還有 error、isLoading、results、show 等方法,可以供開發使用

這次專案只需要使用 open 方法作為按鈕點擊後的展開動作 (下方的上傳圖片按鈕)

https://ithelp.ithome.com.tw/upload/images/20230930/20152073UiWUDshg81.png

// ImageUpload.tsx

const ImageUpload: React.FC<ImageUploadProps> = ({ onChange, ...props }) => {

  return (
    <CldUploadWidget>
      {({ open }) => {
        return <Button onClick={() => open?.()} {...props} /> 
								// props 可由 ImageUpload 傳遞 Button 屬性
      }}
    </CldUploadWidget>
  )
}

// EditComponent.tsx

<ImageUpload
  label="上傳圖片"
  rounded="full"
  size="large"
  className="w-full"
  onChange={(url) => handleUpload(url)}
/>

設置 CldUploadWidget 屬性

必填的屬性為 onUpload 及 uploadPreset:

  • onUpload : 為操控上傳的屬性,會回傳一個 result 物件,包含 event 及 info 屬性,其中 event 為上傳的狀態(成功或失敗),而 info 為照片的所有資訊

    https://ithelp.ithome.com.tw/upload/images/20230930/20152073WBH6u6Ch2e.png

  • uploadPreset : 上傳的識別碼,如果沒設定會無法上傳的!

    • 回到 cloudinary 服務平台,進入 settings

    • 點選 upload 頁籤

      https://ithelp.ithome.com.tw/upload/images/20230930/20152073Mx9QIx87oq.png

    • 看到 Upload presets 欄位,點選 Add upload preset

    • 將 Signing Mode 改為 Unsigned :讓使用者在不需要身份驗證就可以上傳圖片

      https://ithelp.ithome.com.tw/upload/images/20230930/201520738HDMdkDRAL.png

    • 儲存後取得 uploadPreset:supqz33z

      https://ithelp.ithome.com.tw/upload/images/20230930/20152073Kg9SSRLwkD.png

其他 options 屬性可以讓開發者限定或設定上傳圖片的規格,例如:

  • maxFiles:一次最多上傳檔案數量

  • multiple:是否可多選上傳

  • sources:上傳來源設定,除了本地及網址還有:camera、dropbox、facebook、gettyimages、google_drive、image_search、instagram、istock、shutterstock、unsplash 可設置,沒有特別設置就是全部都支援

    https://ithelp.ithome.com.tw/upload/images/20230930/20152073ooAlPETNuh.png

  • maxImageFileSize:圖片上傳大小限制

  • maxImageHeight:圖片高度限制

  • maxImageWidth:圖片寬度限制

  • singleUploadAutoClose:單個檔案上傳後自動關閉,預設為 true

其他更多屬性可以參考:https://cloudinary.com/documentation/upload_widget_reference

const ImageUpload: React.FC<ImageUploadProps> = ({ onChange, ...props }) => {
  const handleUpload = useCallback(
    (result: any) => {
      onChange(result.info.secure_url)
    },
    [onChange]
  )
  return (
    <CldUploadWidget
      onUpload={handleUpload}
      uploadPreset="supqz33z"
      options={{
        maxFiles: 1
      }}
    >
      {({ open }) => {
        return <Button onClick={() => open?.()} {...props} />
      }}
    </CldUploadWidget>
  )
}

設置 handleUpload

在上方的 handleUpload 被封裝為一個共用功能,並回傳上傳後的圖片網址,這讓我在元件外使用 onChange 可以取得網址並進行存取操作,於是此上傳功能在元件外可以這樣寫:

const handleUpload = (url: string) => {
    setCustomValue('customImage', url)
  }

實作成品

設置完成後就可以使用 widget 上傳並取得圖片 url 再進行其他操作

https://imgur.com/M65fGCF

結語

在這個數位時代,開發者面臨的一個不可避免的挑戰是如何處理和儲存媒體資料。Cloudinary 的使用為我們提供了一個在這些重要資源上進行高效能和高效益管理的方法。它從自動優化影像處理到無縫的 CDN 分發,解決了我們在媒體管理上的多個挑戰,讓我們專心創建一個更豐富和更快的用戶體驗。Cloudinary 提供的上傳 UI 元件是我最被吸引的功能之一,並且也是我在多方比較後選擇使用這個服務的決定性因素。

參考資料

https://cloudinary.com/

https://ithelp.ithome.com.tw/upload/images/20230930/20152073KB5Kbq7vnM.png
https://www.ibms.sinica.edu.tw/health/plan.html


上一篇
營養師不開菜單的第十六天 - TypeScript 不夠?使用 Zod 做型別驗證
下一篇
營養師不開菜單的第十八天 - 使用 React-Hot-Toast 實現各種狀態通知
系列文
營養師不開菜單要用 Next.js 13 寫全端30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言