[C#] #10 檔案上傳Base64介紹 - antqtech/KM GitHub Wiki

Base64介紹

什麼是Base64?

Base64 是一種二進位到文字的編碼方式,使用64個字元進行編碼,這些字元包括大寫A到Z,小寫a到z,數字0到9,還有作為填充的 '=' 符號。

Base64表格:

csharp-10-1

資料來源:4(https://www.debugpoint.com/bash-base64-encode-decode/)

為什麼我們使用Base64?

在網路上傳輸資料時,有些字元有時候會導致資料損壞。Base64編碼可以確保資料在傳輸過程中保持完整。傳輸完後,我們可以使用Base64解碼器將Base64字串解碼回原始格式。

Base64如何運作

幾十年前,大多數電腦仍然使用ASCII編碼。如果你不熟悉ASCII,你可以在[2]上了解更多。 每個ASCII字元都可以表示為十進位值。這裡顯示了ASCII表格:

csharp-10-2

資料來源:3(https://simple.m.wikipedia.org/wiki/File:ASCII-Table-wide.svg)

這些十進位值可以轉換為二進位。 我們將3個ASCII字元組合起來,產生4個Base64字元,因為3個字元的位元是3 * 8 = 24位元,24 / 6 = 4個Base64字元。如果ASCII字串的長度不是3的倍數,會加入1或2個填充,使其成為3的倍數。

如果你還是不理解這個過程,可以觀看1(https://www.youtube.com/watch?v=8qkxeZmKmOY&t=97s&ab_channel=ConnorAshcroft)。

檔案上傳Base64

任何類型的檔案都可以用Base64編碼,例如:pdf、jpg、png等。它通常用於通過基於文字的協議(如電子郵件)傳送檔案。

圖片上傳

我們將從後端的角度來看這個範例,因為上傳圖片是透過後端API請求來進行的。

csharp-10-3

上傳圖片時需要的API請求是圖片的Base64格式。

首先,你需要將圖片轉換為Base64。最簡單的方式是使用網路上的"圖片轉Base64轉換器"。例如:5(https://base64.guru/converter/encode/image)。 轉換完成後,你會得到一個非常長的Base64字串,接著就可以上傳這個字串。

csharp-10-4

後端處理Base64字串的程式碼

  // 檢查 公司Logo - 公司LogoBase64有輸入-> 要檢查公司Logo副檔名
  if (ReqAddCard.CCompany_LogoBase64 != "")
  {
      if (ReqAddCard.CCompany_Logo != "")
      {
          CoNewPhoto = true;
      }
      else
      {
          ErrMsg += "請輸入公司Logo附檔名!";
      }

  }

  string CoPhotoErr = "", PPPhotoErr = "", BPPhotoErr = "";

  // 圖片大小上限
  const int MaxImageSizeInBytes = 5 * 1024 * 1024; // 改為5MB

  // 允許的圖片擴展名列表
  string[] AllowedImageExtensions = { ".jpg", ".jpeg", ".png" }; // 移除.gif

  // 存各個照片
  if (CoNewPhoto == true)
  {
      try
      {
          var CofolderPath = System.IO.Path.Combine(_env.ContentRootPath, "Photo/CompanyLogo");
          if (!System.IO.Directory.Exists(CofolderPath))
          {
              System.IO.Directory.CreateDirectory(CofolderPath);
          }

          // 圖片大小驗證
          byte[] CoimageBytes = Convert.FromBase64String(ReqAddCard.CCompany_LogoBase64);
          if (CoimageBytes.Length > MaxImageSizeInBytes)
          {
              CoPhotoErr += "公司Logo圖片大小超過限制!";
          }

          // 圖片格式驗證
          string CofileExtension = ReqAddCard.CCompany_Logo.ToLower();
          if (!AllowedImageExtensions.Contains(CofileExtension))
          {
              CoPhotoErr += "不支持的公司Logo圖片格式!";
          }

          // 儲存圖片
          if (CoPhotoErr == "")
          {
              // 存 公司Logo
              string CoFileName = ReqAddCard.CID + "_" + "Company";
              UtilityFunction.SaveImage(CofolderPath, CoFileName, ReqAddCard.CCompany_LogoBase64, ReqAddCard.CCompany_Logo);
          }
          else
          {
              ErrMsg += CoPhotoErr;
          }
      }
      catch
      {
          ErrMsg += "公司Logo照片儲存發生錯誤!";
      }
  }

我們首先會檢查輸入是否為空。接著設置圖片大小和支援的圖片擴展名。然後我們會檢查想要儲存圖片的目錄。如果所有設定條件都滿足,我們會使用UtilityFunction來儲存圖片。UtilityFunction是一個在其他檔案中撰寫的服務。

UtilityFunction 程式碼:

 public static void SaveImage(string folderPath, string userId, string ImgBase64, string Ext)
 {
     // First, delete existing images for the user
     DeleteImage(folderPath, userId);

     // Save the new image
     File.WriteAllBytes(Path.Combine(folderPath, userId + Ext), Convert.FromBase64String(ImgBase64));
 }

 public static void DeleteImage(string folderPath, string userId)
 {
     string[] extensionsToDelete = { ".jpg", ".jpeg", ".png", ".gif" };
     foreach (var ext in extensionsToDelete)
     {
         if (File.Exists(Path.Combine(folderPath, userId + ext)))
         {
             File.Delete(Path.Combine(folderPath, userId + ext));
             break; // Delete only one file that matches the extension
         }
     }
 }

References: