Windowsフォームで WebBrowser を使用してPDFを表示

## はじめに
Windows Forms アプリケーションで PDF ファイルを表示する方法はいくつかありますが、WebBrowser コントロールを使用することで、特別なライブラリを使用せずに簡単に PDF を表示 できます。C# の WebBrowser を使って、データベースから取得した PDF を表示する方法を解説します。
### WebBrowser を利用するメリット
* 追加のライブラリ不要：WebBrowser は Windows Forms に標準で搭載されているため、追加のパッケージのインストールは不要です。
* シンプルな実装：ファイルを一時フォルダに保存し、そのパスを WebBrowser.Navigate() で開くだけで表示可能。
* ブラウザベースの表示：WebBrowser は Internet Explorer をベースにしているため、PDF リーダーがインストールされていればそのまま開くことができます。

### Windows Forms アプリケーションのセットアップ
### クラスの作成
Windows Forms に WebBrowser コントロールを追加し、フォームを作成します。
```
public partial class FileManagement : Form
{
    private WebBrowser webBrowser;
    private DataGridView dataGridView;
    private Button btnNew;
    private Button btnDisplayWebBrowser;
    private FileServices _fileServices;
    private DataTable _dt;
    private string tempFilePath;

    public FileManagement()
    {
        InitializeControls();
    }

    private void InitializeControls()
    {
        // WebBrowser の設定
        webBrowser = new WebBrowser
        {
            Dock = DockStyle.Fill
        };

        // ボタンの設定
        btnNew = new Button { Text = "新規", Location = new Point(712, 37), Width = 150 };
        btnDisplayWebBrowser = new Button { Text = "表示(WebBrowser)", Location = new Point(712, 86), Width = 150 };
        btnNew.Click += btnAdd_Click;
        btnDisplayWebBrowser.Click += btnOpen_Click;

        // DataGridViewの設定
        dataGridView = new DataGridView { Location = new Point(32, 37), Width = 602, Height = 313 };

        // フォームに追加
        this.Controls.Add(btnNew);
        this.Controls.Add(btnDisplayWebBrowser);
        this.Controls.Add(dataGridView);
        this.Controls.Add(webBrowser);
    }

    private void FileManagment_Load(object sender, EventArgs e)
    {
        LoadFile();
    }

    private void LoadFile()
    {
        _dt = new DataTable();
        _dt.Columns.Add("fileNo");
        _dt.Columns.Add("fileName");

        var data = _fileServices.GetFile(string.Empty) ?? new DataTable();
        foreach (DataRow row in data.Rows)
        {
            _dt.Rows.Add(row["FileNo"], row["FileName"]);
        }
        dataGridView.DataSource = _dt;
        dataGridView.Columns["fileNo"].HeaderText = "ファイルNo";
        dataGridView.Columns["fileName"].HeaderText = "ファイル名";
        dataGridView.Columns["fileNo"].Width = 100;
        dataGridView.Columns["fileName"].Width = 400;
    }
}
```

### PDF ファイルのデータベースへの保存と取得
PDFバイナリファイルをデータベースに保存する。
PDF ファイルを OpenFileDialog で選択し、データベースに保存する処理を実装します。
```
private void btnAdd_Click(object sender, EventArgs e)
{
    using (OpenFileDialog openFileDialog = new OpenFileDialog())
    {
        openFileDialog.Filter = "ファイル (*.pdf)|*.pdf|ファイル (*.*)|*.*";
        openFileDialog.Title = "PDF ファイルを開く";

        if (openFileDialog.ShowDialog() == DialogResult.OK)
        {
            string filePath = openFileDialog.FileName;
            byte[] fileData = File.ReadAllBytes(filePath);
            string fileName = Path.GetFileName(filePath);

            SaveFileToDatabase(fileData, fileName);
            MessageBox.Show("ファイルをデータベースに保存しました！");
        }
    }
}

private async void SaveFileToDatabase(byte[] fileData, string fileName)
{
    await _fileServices.InsertFile(fileName, fileData);
    LoadFile();
}
```
### WebBrowser を使用して PDF を表示する
データベースから取得した PDF を WebBrowser で開くため、以下の処理を実装します。

### PDF 表示ボタンのクリックイベント
```
private void btnOpen_Click(object sender, EventArgs e)
{
    LoadPdfFromDatabase();
}
```
### PDF データをデータベースから取得し、一時ファイルとして保存
```
private async void LoadPdfFromDatabase()
{
    if (dataGridView.SelectedRows.Count > 0)
    {
        DataGridViewRow selectedRow = dataGridView.SelectedRows[0];
        string fileNo = selectedRow.Cells["fileNo"].Value.ToString();

        string where = $"WHERE fileNo = {int.Parse(fileNo)}";
        var data = await _fileServices.GetFile(where) ?? new DataTable();
        
        foreach (DataRow row in data.Rows)
        {
            byte[] pdfData = (byte[])row["fileData"];
            string fileName = row["fileName"].ToString();

            DisplayPdfWithWebBrowser(pdfData, fileName);
        }
    }
}
```

### 一時フォルダに PDF を保存し、WebBrowser で開く
WebBrowser はファイルパスを指定すると自動的にそのファイルを開きます。そこで、PDF を一時フォルダ (C:\TempFile\) に保存し、Navigate() メソッドで開きます。
```
private void DisplayPdfWithWebBrowser(byte[] pdfData, string fileName)
{
    var tempFolderPath = "C:\\TempFile\\";
    tempFilePath = Path.Combine(tempFolderPath, fileName);

    if (!Directory.Exists(tempFolderPath))
    {
        Directory.CreateDirectory(tempFolderPath);
    }

    File.WriteAllBytes(tempFilePath, pdfData);
    webBrowser.Navigate(tempFilePath);
}
```
### 一時ファイルの削除
PDF を開くたびに新しい一時ファイルを作成すると、ファイルが蓄積される可能性があります。そこで、フォームを閉じる際に一時フォルダの PDF を削除する処理を追加します。
```
private void FileManagement_FormClosing(object sender, FormClosingEventArgs e)
{
    DeleteAllFilesInDirectory("C:\\TempFile");
}

private void DeleteAllFilesInDirectory(string directoryPath)
{
    if (Directory.Exists(directoryPath))
    {
        string[] files = Directory.GetFiles(directoryPath);
        foreach (string file in files)
        {
            File.Delete(file);
        }
        MessageBox.Show("一時ファイルを削除しました。");
    }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951101/fe137cbb-7470-e0d5-1940-3492631472f4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951101/ce17f0a0-00fe-9ac9-d725-c0fcdfec7916.png)

## まとめ
✅ 実装のポイント
データベースに PDF を保存
データベースから PDF を取得
取得した PDF を一時フォルダに保存
WebBrowser.Navigate() を使用して PDF を開く
不要なファイルを削除
✅ WebBrowser を利用するメリット
簡単な実装
追加ライブラリ不要
IE がサポートされている環境で動作