在 alpine 中使用 npoi

intro

在 .net 中常使用 npoi 来做 excel 的导入导出,npoi 从 2.4.0 版本开始支持 .netstandard2.0,对于.net core 应用也可以使用 dotnetcore.npoi。

对于 .net core 应用来说,如果没有特殊的需求,alpine 是最适合容器化的基础 docker 镜像,因为镜像大小比较小,无论是对于打包还是下载都很快。

在我的一个 asp.net core 应用中有一个使用 npoi 导出 excel 的功能,我的应用的通过 docker 部署在 k8s 上的,而 docker 镜像是基于 alpine 的,使用到了 npoi 导出一个 excel

npoi 的跨平台实现依赖于 system.drawing.commonsystem.drawing.common 在 linux 上的实现依赖 libgdiplus,需要安装 libgdiplus 才能正常工作,如果没有 libgdiplus 会遇到类似下面这样的异常:

在 linux 上使用 system.drawing.common

  • 在 ubuntu 上安装 libgdiplus,参考 https://www.hanselman.com/blog/howdoyouusesystemdrawinginnetcore.aspx
    :
sudo apt-get install libgdiplus libc6-dev
  • 在 alpine 上安装 libgdiplus

.netcore 打包 docker 镜像的时候我一般选择 alpine 为基本的镜像,因为镜像本身比较小,下载打包都会很快很方便,于是就要找一下是不是可以在 alpine 上安装 libgdiplus,如果不行的话就只好换镜像了

在 alpine 的 packages 网站上找到了 libgdiplus,

目前仍处于测试阶段,还未正式发布,不过已经可以使用,可以通过下面的命令来在 alpine 上安装

apk add libgdiplus --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted

more

安装了 libgdiplus 之后,重新部署再导出测试一下,发现还是不行,现在爆的异常如下:

根据异常提示找到异常的源码 https://github.com/tonyqus/npoi/blob/master/main/ss/util/sheetutil.cs#l445

看异常提示以及代码应该是没有字体导致的异常,然后就在安装 libgdiplus 之后再安装一下字体,随便找了一个字体安装了,安装的是 terminus-font,装了字体之后再测试,就可以正常导出了~

使用的 dockerfile ,完整 dockerfile 见:https://github.com/weihanli/activityreservation/blob/dev/dockerfile

from microsoft/dotnet:2.2-aspnetcore-runtime-alpine
run apk add libgdiplus --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted && \
    apk add terminus-font
# ...

reference

  • https://www.hanselman.com/blog/howdoyouusesystemdrawinginnetcore.aspx
  • https://github.com/tonyqus/npoi/wiki/how-to-use-npoi-on-linux
  • https://github.com/tonyqus/npoi/blob/master/main/ss/util/sheetutil.cs