Preview PDF files as images on your website

by Damiaan Peeters 9. January 2017 20:41

We got a question, and said yes.  If we can do that?  Yes, we can! When you get back at the office you get a cold shiver along your spine when you discover there is no NuGet package available for you to install.

What was the question

The client regularly publishes articles in magazines and journals.  They repost the article on their own website.  Content marketing they told me.  On their old website they had to upload a PDF and a thumbnail of the pdf. 

But dear web builder, you can do better right? Umbraco is a CMS build for content editors and is easy to extent.  Please put the thumbnail automatically inside our website.

The search

There seem to be several products on the market for several thousands of dollars. But the client would not be willing to pay for licenses. The typical conversion could have been like this:

You are building on a large ecosystem of free and open software, right? Yes, dear client. And PDF is an open format right? Yes, dear client. I could not be the first ever to ask this, right? No, dear client.  Can't you ask your friendly colleagues of this friendly CMS?  Sure, dear client. (*)

I tried a few .net managed libraries which I found on the internet.  But most of the managed free PDF libraries you find online are

  1. not working,
  2. incomplete,
  3. in beta
  4. provide a very small subset of what you can do with PDF.
  5. Or simple do not support rendering a PDF to another digital format (like PNG or JPEG).
  6. Or are a wrapper around (some obscure) unmanaged DLL’s

The only way out would be to start a new managed library to read PDF files.  Which can’t be too hard, because it’s mostly PostScript, right?  But going down that path, took already several hours.  Precious time which we did not had.  It was Christmas holiday after all.

From the commercial pallet of products, I did tried Imazen’s Resizer.Net and it worked, but having 2 image processors was complete overkill, and was not playing along with ImageProcessor.  However that could have been me messing around with various dll’s.

Because I lost all hope at finding a complete managed (.net) solution, and because I already found several NuGet packages wrapping GhostScript, we decided to settle.  GhostScript is a pretty mature product after all.

The solution: using ImageProcessor and GhostScript(.net)

We choose GhostScript.Net to be our wrapper around GhostScript.  Mostly because the logo was very nice, certainly compared to the other wrappers available. 

Further we did a small POC proving it worked.  The code is pretty simple:

var rasterizer = new GhostscriptRasterizer();
rasterizer.Open(pdfUri, lastInstalledVersionOfGhostScript, false);
System.Drawing.Image img = _rasterizer.GetPage(_desiredXDpi, _desiredYDpi, pageNumber);
rasterizer.Close();

This very simple code did what we needed.  It converted the (first) page of a PDF to an image format.  It was very simple to create a .Net handler for this to create an image.  But we wanted to have a better dev experience.  And also be able to resize easier.

ImageProcessor to the rescue

The best advice from last year (2016) is: build on the shoulder of giants.  If you have not met James South, it’s a giant.  He is way over 2 meter big, and strong as an elephant. He knows to drink, like a real Scott, and moved to Australia a catch his own food with his bear hands.  Or not.  But he IS a craftsmen and builder of the marvelous ImageProcessor, used and distributed along with Umbraco.

So we wondered if Imageprocessor could support a different file format, like… PDF, we would have a solution.

It turns out that is not too hard.  Just create a new class inherited from FormatBase, override the appropriate members.  If you override the LOAD method of the base class, you could load a PDF, rasterize it, and pass the System.Drawing.Image object to ImageProcessor.  It will handle everything for you?

For example: /media/1234/myPublication.pdf?width=500

Let us serve other clients to!

We do have other clients uploading PDF’s from time to time.  I am pretty sure that we will be installing this plugin to avoid the next support request: “image not showing on website”.

The code is available on github: https://github.com/dampee/ImageProcessor.Plugins.Pdf/

A NuGet package is available too: https://www.nuget.org/packages/ImageProcessor.Plugins.PDF/

 

Let me know what you think of the package.

 

(*) this is fiction, they are actually very nice and polite.  It is only me, myself and I taking blame for the path we took.

 

 

 

 

Error: Update can only be called on a valid data item.

by Damiaan Peeters 31. August 2010 20:12

I had this in a ListView with an EntityDatasource.  But only the ListView had to do something with it…

Cause & solution

You did a copy paste from the EditItemTemplate to the InsertItemTemplate. 

The edit command is not allowed use the Insert command.

Change this:

<asp:Button ID="UpdateButton" runat="server" CommandName="Update"  Text="Update" />

To:

<asp:Button ID="InsertButton" runat="server" CommandName="Insert" Text="Insert" />

UrlEncode without HttpContext

by Damiaan Peeters 25. August 2009 12:19

Yesterday I had to use the UrlEncode function.  UrlEncoding is used to converts all illegal characters in a URL to valid characters.  For example the space will be converted to %20.

Fortunately the .Net Framework supplies a UrlEncode method on its Server Class.  The server class resides in the HttpContext.  The problem is that you need a HttpContext Instance to call this class.

Using Reflector, I found out that the UrlEncode method on the Server Property uses the HttpUtility class.

image

So, instead of using this: HttpContext.Current.Server.UrlEncode(text)
you can also use: HttpUtility.UrlEncode(text)

The only thing to use this is to include the System.Web assembly in your project.

EXECUTE permission denied on object 'aspnet_CheckSchemaVersion', database 'myDB', schema 'dbo'.

by Damiaan Peeters 7. April 2009 18:27

Problem

Today I launched the aspnet_regsql.exe.  Unfortunately I received the following error:

EXECUTE permission denied on object 'aspnet_CheckSchemaVersion', database 'myDB', schema 'dbo'.

Solution

Take the properties of the “NT Autority\Network Service” user.  Select the myDB database and add all the necessary Roles like aspnet_Membership_FullAccess to the user. 

image

In the screenshot are all the databaseroles added.

Tags: ,

Asp.Net | SQL

ASP.Net Membership API Cannot resolve collation conflict for equal to operation

by Damiaan Peeters 31. December 2008 09:36

Error

I was using the ASP.NET SQL Server Setup Wizard (aspnet_regsql.exe) to deploy te database to the production SQL Server 2005.

image

Creation or change of the SQL Server database failed.

Setup failed.

Exception:
An error occurred during the execution of the SQL file 'InstallRoles.sql'. The SQL error number is 468 and the SqlException message is: Cannot resolve the collation conflict between "Latin1_General_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
[cut]

SQL file loaded:
InstallRoles.sql

Commands failed:

[cut] …  the failed SQL code

SQL Exception:
System.Data.SqlClient.SqlException: Cannot resolve the collation conflict between "Latin1_General_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
Cannot resolve the collation conflict between "Latin1_General_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
[cut
]…
Cannot resolve the collation conflict between "Latin1_General_CI_AS" and "SQL_Latin1_General_CP1_CI_AS" in the equal to operation.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Web.Management.SqlServices.ExecuteFile(String file, String server, String database, String dbFileName, SqlConnection connection, Boolean sessionState, Boolean isInstall, SessionStateType sessionStatetype)

Cause

Apparently this error happend when creating the asp.net membership stored procedures: aspnet_UsersInRoles_AddUsersToRoles or aspnet_UsersInRoles_RemoveUsersFromRoles.

The reason is pretty straithforward.

The aspnet_Roles table uses collation “latin1_General_CI_AS”.

image

While my database has a SQL_Latin1_General_CP1_CI_AS collation by default (just like my SQL server collation).

image

Solution

Use the SQL Profiler to get the Code of the of the Stored procedure which need to be created.  The SQL scripts of the ASP.Net Membership can also be found under: C:\Windows\Microsoft.NET\Framework\v2.0.50727  (InstallRoles.sql)

Change the line(s) in the scripts:

look for this line: DECLARE @tbNames table(Name nvarchar(256) NOT NULL PRIMARY KEY) and add the collation like specified in the “aspnet_Roles.RoleName” column.  Your new line should look like this:

DECLARE @tbNames table(Name nvarchar(256) COLLATE Latin1_General_CI_AS NOT NULL PRIMARY KEY)

You need to do this for the 2 stored procedures.

Asp.Net Debug (breakpoints) not working in VS2008

by Damiaan Peeters 14. December 2008 10:42

Problem

I set a breakpoint and my debugger is not stopping at the breakpoint.  Debug is configured in the Web.Config:

<compilation debug="true">
    <assemblies>

My assembly is compliled in Debug mode: debug - any cpu

Solution

The last thing to check is of cource the Project Properties. 

Go to the tab “Web”, just below Signing.
image

You will see at the bottom a section Debuggers.
image

Activate the ASP.NET checkbox and your breakpoints will halt your running code again.

Microsoft support can be found here for some common problems: INFO Common Error When you Debug ASP.Net Applications in Visual Studio .NET and especially here: PRB: Visual Studio .NET Debugger Does Not Stop on Breakpoints When You Debug ASP.NET Pages

Dynamic themes in ASP.NET 2.0 (C#)

by Damiaan Peeters 22. March 2008 12:11

Today I looked at the ASP.NET 2.0 Themes.  I've been using them for a long time, but I never knew that you can set a default theme in the web.config.

Just add this to the system.web section

<pages styleSheetTheme="Black"/>

Further more I needed to change my theme dynamically.  I found an interesting article on this topic on CodeProject.

CodeProject: Dynamic themes in ASP.NET 2.0 (C#).

Who.I.am

Certified Umbraco Master, Part of Umbraco Certified partner comm-it, .Net and Azure developer, seo lover. Magician in my spare time.

Month List