[英]DrawingCore exception in azure function c# .net
未处理的异常: System.MemberAccessException :
Object is busy and cannot state allow this operation [GDI+ status: ObjectBusy]
at System.DrawingCore.GDIPlus.CheckStatus(Status status)
at System.DrawingCore.Image.Dispose(Boolean disposing)
at System.DrawingCore.Image.Finalize()
以下代码偶尔会发生此错误。 我正在使用 sautinsoft 库,而 imageFormat 是 System.DrawingCore.Imaging。
using (Stream fs = pdfFile.OpenReadStream())
{
await Task.Run(() => _pdfFocus.OpenPdf(fs));
if (_pdfFocus.PageCount > 0)
{
_pdfFocus.ImageOptions.ImageFormat = imageFormat;
_pdfFocus.ImageOptions.Dpi = 100;
_pdfFocus.ImageOptions.JpegQuality = 90;
for (int i = 1; i <= _pdfFocus.PageCount; i++)
{
await Task.Run(() => pdfPagesAsImageFileList.Add(_pdfFocus.ToImage(i)));
}
}
Task.WaitAll();
}
就像 Marc 所说的 azure 有沙箱限制,并且大多数将 pdf 转换为图像的 .net 包需要 GDI,这不受支持。 现在我只找到一个包来使用 .net 来实现它。 您可以尝试使用GhostScript和Magick.NET-Q16-AnyCPU来实现它。
安装Ghostscript
,您将在 bin 文件夹中获得gsdll32.dll
文件。 下面是我的测试代码,将02.pdf和gsdll32.dll复制到kudu wwwroot
文件夹下。
using System.Net.Http;
using ImageMagick;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
namespace FunctionApp6
{
public static class Function1
{
[FunctionName("Function1")]
public static void Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log,ExecutionContext context)
{
log.Info("C# HTTP trigger function processed a request.");
MagickNET.SetGhostscriptDirectory(context.FunctionAppDirectory);
log.Info(context.FunctionAppDirectory);
MagickReadSettings settings = new MagickReadSettings();
// Settings the density to 300 dpi will create an image with a better quality
settings.Density = new Density(300, 300);
using (MagickImageCollection images = new MagickImageCollection())
{
log.Info(context.FunctionAppDirectory + "\\02.pdf");
// Add all the pages of the pdf file to the collection
images.Read(context.FunctionAppDirectory+"\\02.pdf", settings);
int page = 1;
foreach (MagickImage image in images)
{
log.Info(context.FunctionAppDirectory + "\\outpng" + page + ".png");
// Write page to file that contains the page number
image.Write(context.FunctionAppDirectory + "\\outpng" + page + ".png");
// Writing to a specific format works the same as for a single image
//image.Format = MagickFormat.Ptif;
//image.Write(SampleFiles.OutputDirectory + "Snakeware.Page" + page + ".tif");
page++;
}
}
log.Info("convert finish");
}
}
}
这是天蓝色的结果图片。
Azure Functions 在安全环境(也称为沙箱)中运行。 这个沙箱有很多限制,所有限制都在这里描述: https : //github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox
在您的特定情况下,您受到限制,因为该过程无法访问上面链接的页面中提到的 GDI32:
为了彻底减少攻击面,沙箱阻止了几乎所有的 Win32k.sys API 被调用,这实际上意味着大部分 User32/GDI32 系统调用被阻止。 对于大多数应用程序,这不是问题,因为大多数 Azure Web 应用程序不需要访问 Windows UI 功能(毕竟它们是 Web 应用程序)。
有多个库用于将 HTML 转换为 PDF。 许多 Windows/.NET 特定版本利用 IE API,因此广泛利用 User32/GDI32。 这些 API 大部分都在沙箱中被阻止(无论计划如何),因此这些框架在沙箱中不起作用。
有一些框架没有广泛利用 User32/GDI32(例如 wkhtmltopdf),我们正在努力在 Basic+ 中启用这些,就像启用 SQL 报告一样。
您可能需要找到一种替代方法来创建 PDF 文件或将计算移到 Azure Functions 之外。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.