浅谈 C# 与 Data URI

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

有看過這種HTML嗎?

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>Data URI</title>

<link href="data:text/css;base64,77u/aW1nICANCnsNCiAgICBib3JkZXI6IDFweCBzb2xpZCByZWQ7DQp9DQo=" rel="stylesheet" type="text/css" />

</head>

<body>

<form id="form1" runat="server">

<img src="data:image/gif;base64,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" />

</form>

</body>

</html>

在HTML裡link的href及img的src,並沒有指向某個URL,而是直接嵌入一段Base64編碼,而IE8+, Firefox, Safari, Opera, Chrome都能正確顯示其中的圖檔與CSS設定。

這種表示方法叫做data URI schema,是新一代瀏覽器支援的檔案資料表現格式,允許在網頁裡以字串形式直接內嵌圖檔、CSS檔案,進而達到以下好處:

  1. 瀏覽器不用為了下載圖檔、CSS另外發動HTTP Request。每次HTTP傳輸產生的額外資料量(HTTP Header、TCP/IP Header...等),累積下來多半會大於使用Base64編碼二進位資料所增加的資料量(每3個Byte增加一個Byte),事實上內嵌成Base64字串反而較節省頻寬。
  2. 基於TCP傳輸特性,傳送一個大檔案會比連續傳送多個拆解的小檔更快速有效率。(HTTP Keep-Alive可以改善傳送多個小檔案效率不佳的問題,但並不能徹底解決)
  3. 使用HTTPS(SSL)傳輸時,因為HTTPS Request的額外程序更多,內嵌資料做法的改善更明顯。
  4. 瀏覽器通常會有同時使用HTTP連線數的上限(例如: 兩條),將所有需要資料一次下載回來,可以避免持續佔用寶貴的連線資源。
  5. 以往在網頁式的Rich Text編輯器裡處理貼上圖檔,得將圖檔上傳至伺服器端某處,再將URL丟回編輯器中。使用內嵌資料寫法,可讓網頁編輯文字要內嵌圖檔容易多了。

當然,凡事不會有利無害,網頁內嵌資料的做法也有其缺點:

  1. 因圖檔內容被綁在網頁中,若為動態網頁每次內容都會變化,就無法透過快取加速及節省頻寬,網頁內容含圖檔資料,每次都得重新下載。
  2. 當檔案資料有變化時,所有內嵌它的網頁都要重新產生編碼。
  3. IE8以上的版本才有支援,且限制大小不可超過32KB
  4. Base64會讓內容變大33%,但若Web Server端啟用GZIP壓縮,增加的大小可以縮小到2-3%。
  5. 對資安軟體來說,Data URI增加了網頁內容檢驗的難度。

IE從IE8開始才支援這種Data URI的做法,且基於安全、效率的考量,加入了一些限制:

  • 不支援Javascript檔內嵌,避免惡意程式藏匿其中,逃避Script過濾機制。
  • 內嵌檔案大小不可超過32KB。
  • 支援格式包含: object (images only) , img, ``input type=image, ``link
    以及CSS宣告,例如:``background-image, background, list-style-type, list-style等。

我寫了一小段ASP.NET程式用來產生Data URI字串,最前面的HTML就是透過這個工具做出來的,大家也可以玩看看。

using System;

using System.IO;

public partial class DataURI_Default : System.Web.UI.Page

{

private string GenDataURI(string contentType, string filePath)

{

byte\[\] buff = File.ReadAllBytes(filePath);

return string.Format("data:{0};base64,{1}",

contentType, Convert.ToBase64String(buff));

}

protected void Page_Load(object sender, EventArgs e)

{

string path = Request"path" ?? "";

if (!string.IsNullOrEmpty(path) &&

File.Exists(Server.MapPath(path)))

{

string contentType = "";

switch (path.ToLower().Substring(path.Length-4, 4))

{

case ".jpg":

contentType="image/jpeg";

break;

case ".gif":

contentType="image/gif";

break;

case ".png":

contentType="image/png";

break;

case ".htm":

contentType="text/html";

break;

case ".css":

contentType="text/css";

break;

default:

Response.Write("Not supperted file type!");

Response.End();

break;

}

Response.Write(GenDataURI(contentType, Server.MapPath(path)));

Response.End();

}

}

}

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
曹牧7 小时前
C#:未被引用的函数
c#
上位机妹子13 小时前
EF Core 两种继承映射:每层次一张表(TPH)与每类型一张表(TPT)
数据库·c#·.netcore·ef core
小羊没烦恼!14 小时前
jQuery1.5的改进细节
java·服务器·开发语言·前端·c#
下页、再停留15 小时前
【C#桌面客户端系列学习-8】批量导出数据为csv格式
开发语言·c#·visual studio
波力海苔夹心脆67516 小时前
C# 视觉检测实战:PLC 按钮触发 VisionPro 检测,OK 亮灯 / NG 灭灯(西门子 PLC,含界面显示与图片存档)
开发语言·经验分享·c#·自动化·视觉检测·.net
kim17 小时前
一个人 + AI,用 WinForms 搓了个 376KB 的 Windows 便签:便签 / 截图 / 标注 / OCR / 待办全塞进去了
c#
hez201018 小时前
一行代码在 .NET 项目里启用 Satori GC
c#·.net·.net core·gc·clr
宇卿.18 小时前
C#语句:
开发语言·c#
咕白m62518 小时前
使用 C# 将 TIFF 转换为 PDF
前端·c#
JQLvopkk19 小时前
HslCommunication,一个工具测遍所有 PLC
开发语言·人工智能·c#·交互