使用 Pdfium 渲染器渲染 .ai

Render .ai with PdfiumRenderer

我正在尝试使用 ImageResizer 生成 .ai 文件 (Adobe Illustrator) 的缩略图。由于官方 Adob​​e Acrobat Reader 实际上可以打开这些文件,我假设 PdfiumRenderer 也可以做到这一点。

事实上,我已经通过将 .ai 文件重命名为 .pdf 进行了测试,缩略图显示得很好。显然,如果没有重命名它是行不通的,因为没有为该文件扩展名注册插件。并且以这种方式重命名客户端提供的文件似乎也不是一个好的解决方案。

我尝试编写一个最小的自定义插件,它继承自 PdfiumRenderer,但将 .ai 文件扩展名添加到支持的文件类型列表中。然后 ImageResizer 将正确捕获 .ai 请求但显示错误。

HTTP/1.1 500 Internal Server Error 
Cache-Control: public 
Content-Type: image/jpeg; charset=utf-8 Server: Microsoft-IIS/10.0 
X-AspNet-Version: 4.0.30319 
X-Powered-By: ASP.NET 
Content-Length: 7472

[ArgumentException]: Parameter is not valid.
   at System.Drawing.Bitmap..ctor(Stream stream, Boolean useIcm)
   at ImageResizer.ImageBuilder.DecodeStream(Stream s, ResizeSettings settings, String optionalPath)
   at ImageResizer.ImageBuilder.LoadImage(Object source, ResizeSettings settings, Boolean restoreStreamPos)
[ImageCorruptedException]: File may be corrupted, empty, or may contain a PNG image with a single dimension greater than 65,535 pixels.
   at ImageResizer.ImageBuilder.LoadImage(Object source, ResizeSettings settings, Boolean restoreStreamPos)
   at ImageResizer.ImageBuilder.BuildJob(ImageJob job)
   at ImageResizer.ImageBuilder.Build(ImageJob job)
   at ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings, Boolean disposeSource, Boolean addFileExtension)
   at ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings, Boolean disposeSource)
   at ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings)
   at ImageResizer.InterceptModule.<>c__DisplayClass5_0.<HandleRequest>b__1(Stream stream)
   at ImageResizer.Plugins.DiskCache.CustomDiskCache.<>c__DisplayClass29_0.<TryWriteFile>b__0()
   at ImageResizer.Plugins.DiskCache.LockProvider.TryExecute(String key, Int32 timeoutMs, LockCallback success)
   at ImageResizer.Plugins.DiskCache.CustomDiskCache.TryWriteFile(CacheResult result, String physicalPath, String relativePath, ResizeImageDelegate writeCallback, Int32 timeoutMs, Boolean recheckFS)
   at ImageResizer.Plugins.DiskCache.CustomDiskCache.GetCachedFile(String keyBasis, String extension, ResizeImageDelegate writeCallback, Int32 timeoutMs, Boolean asynchronous)
   at ImageResizer.Plugins.DiskCache.DiskCache.Process(IResponseArgs e)
   at ImageResizer.Plugins.DiskCache.DiskCache.Process(HttpContext context, IResponseArgs e)
   at ImageResizer.InterceptModule.HandleRequest(HttpContext context, HttpModuleRequestAssistant ra, IVirtualFile vf)
   at ImageResizer.InterceptModule.CheckRequest_PostAuthorizeRequest(Object sender, EventArgs e)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

如果对自定义插件有更多经验的人或来自 Imazen 的人可以帮助我,我将不胜感激。

好吧,我终于成功了,我的项目现在支持 PDF 和 AI 缩略图,包括支持空白修剪、Azure 存储、磁盘缓存等!

Nathanael 没有直接提供解决方案,而是为我指出了正确的方向(谢谢!)。 DecodeStream 方法提供了一个可选的路径字符串,如果该路径不以 .pdf 结尾,显然 PdfiumRenderer 会崩溃。这里的技巧是隐藏这条路径并传递空值。

尽管从 PdfiumRendererPlugin 继承时无法覆盖 DecodeStream 方法,但我确实不得不编写比以前多一点的代码。这是完整的代码:

public class IllustratorPlugin : BuilderExtension, IPlugin, IFileExtensionPlugin, IIssueProvider, IQuerystringPlugin {

    private readonly PdfiumRendererPlugin BasePlugin;

    public IllustratorPlugin() : base() {

        BasePlugin = new PdfiumRendererPlugin();

    }

    public IEnumerable<IIssue> GetIssues()
        => BasePlugin.GetIssues();

    public IEnumerable<string> GetSupportedFileExtensions()
        => new string[] { ".ai" };

    public IEnumerable<string> GetSupportedQuerystringKeys()
        => BasePlugin.GetSupportedQuerystringKeys();

    public IPlugin Install(ImageResizer.Configuration.Config c) {

        BasePlugin.Install(c);
        c.Plugins.add_plugin(this);

        return this;

    }

    public bool Uninstall(ImageResizer.Configuration.Config c) {

        c.Plugins.remove_plugin(this);
        return BasePlugin.Uninstall(c);

    }

    public int MaxHeight {
        get => BasePlugin.MaxHeight;
        set => BasePlugin.MaxHeight = value;
    }

    public int MaxWidth {
        get => BasePlugin.MaxWidth;
        set => BasePlugin.MaxWidth = value;
    }

    public int DefaultHeight {
        get => BasePlugin.DefaultHeight;
        set => BasePlugin.DefaultHeight = value;
    }

    public int DefaultWidth {
        get => BasePlugin.DefaultWidth;
        set => BasePlugin.DefaultWidth = value;
    }

    public override Bitmap DecodeStream(Stream s, ResizeSettings settings, string optionalPath)
        => BasePlugin.DecodeStream(s, settings, null);

}

在 global.asax 中,我刚刚添加了这一行:

new IllustratorPlugin().Install(ImageResizer.Configuration.Config.Current);

然后可以从 web.config.

中删除 PdfiumRenderer 插件