Imagickを使ってPDFからサムネイルを作成し、S3にアップロードする

# 前置き

* Imagick、S3ともに知識が浅いです。参考程度にお願いします。

# 前提

* CentOS6.7(ローカルの開発環境なのでEC2じゃないです)
* Imagick, フォント系モジュールはインストール済み
* PDFの１枚目をJPEGに変換してサムネイルとしたい

# 始めの構想

1. ImagickでPDFの１ページ目をJPEGに変換し、S3に直接保存
　こちらは、エラーが多発しなかなか実装できませんでした。
　エラー文を見る限り、ファイルの実体が無いとアップロードできないようにうかがえました。

2. 表示するときだけ、JPEGにして表示する（実は試していない）

# 最終的な構想

ImagickでPDFの１ページ目をJPEGに変換し、自身のサーバー内に一次保存。
一次保存したファイルをS3へアップロードして、サーバー内のファイルを削除。

# 準備

- Imagickのインストール
- AWS SDK for PHPをCakePHP内のPluginディレクトリに入れておく（参照できればどこでもよし）
- PDFで使用されるであろうFont群もダウンロードしておく( **imagick pdf** とかでググってると、ここら辺たくさん出てくる)

# コード

```php:HogeController.php
<?php
/**
 * HogeController
 * ほげほげするコントローラー
 **/
Class HogeController extends AppController {

  public $components = ['Amazon'];

～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～～

  /**
   *  資料のサムネイルを作成する
   *  @param string $fileName 元ファイルのパス
   *  @return void
   * */
  private function _createThumnail($fileName){
    $name = PREFIX_DOCUMENT.pathinfo($fileName, PATHINFO_FILENAME).".jpg"; //サムネイルのファイル名
    $thumbname = PATH_TMP_IMG_DIR.DS.$name; //サムネイルの一次保存先

    /* サムネイルの作成 */
    $thumbImg = new Imagick(); // 画像の読み込み
    $thumbImg->readImage(AWS_S3_HOSTNAME.AWS_S3_BUCKET."/xxxx/".$fileName); // 元ファイルのパス
    $thumbImg->setImageIndex(0); // １ページ目を指定
    // $thumbImg->resizeImage(210, 180, Imagick::FILTER_POINT, 2); リサイズしたさあるけど、劣化激しい・・・
    $thumbImg->setImageFormat ("jpeg"); // jpegにする

    /* リサイズした画像を保存する */
    try {
      $thumbImg->writeImage($thumbname); // ファイルとして保存する
      $ret = $this->Amazon->putObject("xxxx/".$name, $thumbname); // S3へ保存

      if ( $ret !== "" ) {
        unlink($thumbname); // 一時ファイル削除
      }

      $thumbImg->destroy(); // imagickで作成したイメージ削除（これの必要性があまりわかってないけど、メモリ上で残るとかかな？）
    } catch (Exception $e) {
      echo $e->getMessage();
    }
  }

```


```php:AmazonComponent.php
<?php
/**
 * AWS SDK for PHP
 * 
 **/
require ROOT. DS . APP_DIR . DS .'Plugin/AmazonSDK/vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Credentials\Credentials;

App::uses('Component', 'Controller');
class AmazonComponent extends Component {

  /**
   * S3へのファイルアップロード
   * @params $key string 保存先パス + ファイル名
   * @params $file string 実ファイルのパス
   * @return string 保存先
   **/
  function putObject($key, $file){
    try {
      $credentials = new Credentials(AWS_S3_KEY, AWS_S3_SECURITY);
      $aws = S3Client::factory([
        'version'    => AWS_S3_VERSION,
        'credentials' => $credentials,
        'region' => AWS_S3_REGION,
      ]);
      $result = $aws->putObject([
        'Bucket' => AWS_S3_BUCKET,
        'Key'    => $key,
        'SourceFile'   => $file,
        'StorageClass' => AWS_S3_STORAGE,
      ]);
      return $result['ObjectURL'];
    } catch (Exception $e) {
      echo $e->getMessage();
      return "";
    }
  }

  /**
   * S3のファイル削除
   * @params $file string 保存先パス + ファイル名
   * @return void
   **/
  function removeObject($file){
    try {
      $credentials = new Credentials(AWS_S3_KEY, AWS_S3_SECURITY);
      $aws = S3Client::factory([
        'version'    => AWS_S3_VERSION,
        'credentials' => $credentials,
        'region' => AWS_S3_REGION,
      ]);
      $result = $aws->deleteObject([
        'Bucket' => AWS_S3_BUCKET,
        'Key'    => $file
      ]);
    } catch (Exception $e) {
      echo $e->getMessage();
    }
  }
}


```

# その他

## ファイルサイズ制限に引っかかる

4MBくらいのサイズのPDFをアップできませんでした。
nginxやphpの設定を見てみると、アップロード制限が指定してあります。
（nginxは1MBとかですね）
その為、設定ファイルを編集し各サービスの再起動が必要です。

```shell-session
$ sudo vim /etc/php.ini
```

以下の通り書き換える。

```/etc/php.ini
max_input_vars = 100000000
upload_max_filesize = 100M
post_max_size = 110M
```


```shell-session
$ sudo vim /etc/nginx/nginx.conf
```

以下の通り書き換える。(serverの中じゃ効かないカモです！)

```/etc/nginx/nginx.conf
http {
  client_max_body_size 200000000;
  ...
```

nginxとphpの再起動

```shell-session
$ sudo service nginx -t
$ sudo service nginx -s reload
$ sudo service php-fpm restart
```

# 変更履歴

## 2017/01/06 追記: フォームの内容がある程度の容量を超えるとpostが出来ない

php.iniに「max_input_vars」と「post_max_size」の指定を追加しました。

```ini:/etc/php.ini
max_input_vars= 100000000
post_max_size = 110M
```