1. 程式人生 > 其它 >.NET Core 5.0專案使用System.Drawing.Common庫在Linxu系統中報“Gdip”異常

.NET Core 5.0專案使用System.Drawing.Common庫在Linxu系統中報“Gdip”異常

背景:

  最近我有一個專案中有匯出二維碼圖片的需求,我用Gma.QrCodeNet.Core元件實現,在Window系統上執行一切都是正常的,釋出到測試環境CentOS系統後這個介面丟擲System.TypeInitializationException:The type initializer for 'Gdip' threw an exception -->System.DllNotFoundException:Unable to load DLL 'libgdiplus' ; The specified module could not be found. 這個錯誤是在初始化Gdip時出現異常,原因時沒有載入到libgdiplus 這個DLL。

知其所以然:

  出現這個錯誤是因為Gma.QrCodeNet.Core元件依賴了微軟的System.Drawing.Common.dll庫,早期的.NET Core版本是沒有System.Drawing.Common.dll庫的,微軟在.NET Core3.0開始提供了這個庫,它庫封裝了GDI+繪圖功能。GDI 全名為:Graphics Device Interface(圖形裝置介面),而GDI是屬於Windows系統下的圖形裝置介面,那麼.NET Core有沒有實現Linux系統下的“GDI”呢?答案是沒有。

  當.NET還沒有實現跨平臺的時候,mono團隊就替微軟.NET跨平臺操碎了心,mono大量的應用在遊戲行業,遊戲開發者們既依賴微軟的unity3d開發庫,又不想使用臃腫低效且閉源的Windows系統。為了讓.NET程式碼執行在Linux系統上,因此誕生了mono專案,大家都知道後來mono被微軟招安。而mono團隊實現了.NET Core在LinuxOS和MacOS系統下的DGI相關介面,他就是libgdiplus。

因此System.Drawing.Common.dll庫在Windows系統下繼續呼叫原來的GDI實現,在MacOS和LinuxOS下則依賴libgdiplus來實現繪圖能力。

  所以,我的專案在Window系統正常執行,在Linxu上則丟擲System.TypeInitializationException:The type initializer for 'Gdip' threw an exception -->System.DllNotFoundException:Unable to load DLL 'libgdiplus' ; The specified module could not be found. 異常。要解決這個問題就很簡單了,只需要給Linux系統安裝libgdiplus

庫就行了。

解決問題:

1.系統簡單通過dotnet 命令直接執行在linux上,則直接在系統中安裝libgdiplus就可以了。

CentOS安裝命令:

yum install libgdiplus-devel -y
ln -s /usr/lib64/libgdiplus.so /usr/lib/gdiplus.dll
ln -s /usr/lib64/libgdiplus.so /usr/lib64/gdiplus.dll

Ubuntu安裝命令

sudo curl https://raw.githubusercontent.com/stulzq/awesome-dotnetcore-image/master/install/ubuntu.sh|sh

2.在Docker中執行的專案因為每次重新構建Docker映象原來的安裝就沒用了,所以有兩個方案,

  第一個方案是基於微軟的映象把libgdiplus加入重新打包一個新的映象。以後重新部署專案都基於這個新的映象來構建。

  第二個方案是每次部署專案構建映象時自動安裝libgdiplus庫。那麼就需要將安裝libgdiplus庫的命令新增到Dokerfile檔案中。檔案內容如下:

FROM mcr.microsoft.com/dotnet/aspnet:5.0
MAINTAINER pudefu

LABEL description="某某某專案"
LABEL version="1.0"
WORKDIR /app
COPY . .

# 切換apt源為網易
RUN echo "" > /etc/apt/sources.list \ 
   && echo "deb http://mirrors.163.com/debian/ stretch main non-free contrib" >> /etc/apt/sources.list \ 
   && echo "deb http://mirrors.163.com/debian/ stretch-updates main non-free contrib" >> /etc/apt/sources.list \ 
   && echo "deb http://mirrors.163.com/debian/ stretch-backports main non-free contrib" >> /etc/apt/sources.list \ 
   && echo "deb-src http://mirrors.163.com/debian/ stretch main non-free contrib" >> /etc/apt/sources.list \ 
   && echo "deb-src http://mirrors.163.com/debian/ stretch-updates main non-free contrib" >> /etc/apt/sources.list \ 
   && echo "deb-src http://mirrors.163.com/debian/ stretch-backports main non-free contrib" >> /etc/apt/sources.list \ 
   && echo "deb http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib" >> /etc/apt/sources.list \ 
   && echo "deb-src http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib" >> /etc/apt/sources.list
# 安裝gdiplus RUN apt
-get update -y && apt-get install -y libgdiplus && apt-get clean && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll EXPOSE 8888 RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone ENV ASPNETCORE_ENVIRONMENT Development #ENTRYPOINT ["dotnet","XXXXXX.dll"]

這裡安裝libgdiplus庫只需要增加如下命令即可。

RUN apt-get update -y && apt-get install -y libgdiplus && apt-get clean && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll

但是libgdiplus庫原生提供地址下載太慢,至少正常人都不能忍受。所以我們需要將下載源修改為國內源就,比如阿里,騰訊,網易等都可以。最開始我使用的是阿里雲的源,但是遇到鑑權相關問題,換了網易的源則沒有相關問題,騰訊的沒有測試。

至此,問題解決,又可以愉快的寫程式碼了。

提示:System.Drawing.Common.dll庫