C#(MVC5)で PDFのプレビュー機能を作った話

概要

WebでPDFのプレビュー機能を作りたいため、PDFをJPGに変換し、さらにBase64エンコードした話です。

環境

  • サーバOS:Winサーバ 2012R2
  • 提供:Webアプリ
  • F/W:MVC5.Net
  • このために利用したライブラリ:Magick.NET

    こんなWebシステム作ってました。このシステムではファイルを添付することができます。用途は主にPDFを想定してました。 当初の使い方としてはブラウザからダウンロードして見てもらえればいいと思ってましたが、一部のユーザから「ダウンロードしたらブラウザ上でPDFファイルが開いた。そのあとどうやって元の画面に戻ればいいかわからない」と問い合わせがあったそうです。 仕方なしにPDFをブラウザ上でプレビュー表示できるようにした話です。

実装方針

  • 制約事項

    • PDFはサーバの非公開領域においてある
    • IE対応も必要

    初めはサーバサイドでPDFをBase64エンコードし、フロント側で下記データで表示しようとしました。

    <object data="data:application/pdf;base64,Base64エンコードしたデータ"  type="application/pdf"></object>
    

    が、表示されません。ググるとIEでは非対応)だそうです。許すまじIEですね。

ということで作戦変更です。

  1. サーバサイドでPDFを画像変換し更に変換したものをBase64エンコードする
  2. クライアントではBase64したデータをimgタグに注入する

実装

1研究中:C# Magick.NETを使ってみる。 こちらをかなり参考にしつつ進めていきました。1研究中さんを参考にNugetからMagick.NETをインストールします。 実際にPDFから画像に変換した後にBase64へしたのがこちら。

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using NLog;
using System.Web;
using ImageMagick;

namespace TestWeb.Controllers
{

    public class APIHogeController : ApiController
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        public string GetBase64File()
        {

            try
            {
                var filePath = "C:\\\temp\\hogehoge.pdf";

                // PDFファイルを画像に変換
                var imagePath = convertPdf2Image(filePath);

                // 画像をBase64エンコード
                return Convert.ToBase64String(File.ReadAllBytes(imagePath));
            }
            catch (Exception e)
            {
                logger.Error(String.Format(e.ToString()));
                logger.Error(String.Format(e.StackTrace));
                throw new Exception();
            }

        }

        // PDF を画像ファイルに変換
        private string convertPdf2Image(string pdfPath)
        {

            // 画像ファイルの保存場所
            var imagePath = "C:\\\temp\\fugafuga.jpg";

            // ImageMagick の設定
            MagickReadSettings settings = new MagickReadSettings();
            settings.Density = new Density(150);

            using (MagickImageCollection images = new MagickImageCollection())
            {
                images.Read(pdfPath, settings);

                using (IMagickImage vertical = images.AppendVertically())
                {
                    vertical.Alpha( AlphaOption.Remove);  // 透過を除去(透過部分が黒くなるので)
                    vertical.Write(imagePath);
                }
            }
            return imagePath;
        }

    }
}

ApiControllerが元になってたり、不要なものをインポートしてますが脳内置換していただけると幸いです。 上記の要領でBase64に変換したものをフロントにてimgタグに注入すればOKです。
対象ブラウザ:IEを謳ってなければこんなことをしなくて済んだんですよね。IE許すまじ。。

0 件のコメント :

コメントを投稿