[「413 Request Entity Too Large 」 Nginx で、ファイルのアップロードエラーの対処方法

# はじめに
WebサーバーとしてNginxを使用したサーバーで、3GBのsqlファイルをadminerでインポートする際、`413 Request Entity Too Large`や`504 Gateway Time-out`のエラー対処に手間取ったため、方法をまとめます。

基本的に、データ量が多いと、`データの送受信の時間を伸ばす`、`データファイル容量の上限を増やす`必要があります。

sqlファイルのインポートに限らず、PHPで実行時の`504 Gateway Time-out`エラー対処に使用できる記事になります。

# 前提条件
- DB管理はadminerを使用。phpmyadminでも問題なし
- nginxを使用
- EC2にadminerを導入（以下の記事参考

https://qiita.com/holdout0521/items/d559ed8ab24aaaafd876


# sqlファイルのインポート方法

1. adminer.php が配置されているディレクトリ内に、エクスポートしたsqlファイルをそのまま、アップロードします。私の場合、圧縮タイプの`.gz`タイプだとインポートできませんでしたので、ファイルでアップロードしました。
1. アップロードしたsqlファイルを`adminer.sql`にリネームします。
1. 下記の画像のように、`サーバーから実行`をクリックします。

![スクリーンショット 2021-11-11 22.44.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/8e5ffa74-f42e-0ce9-1733-59a2bcd3927b.png)

実行すると、数十秒で以下のエラーが発生します。

```
504 Gateway Time-out
```

# 結論
以下の`3つのファイル`と`ELB`を修正します。
- nginx.conf
- php.ini
- php-fpm.conf
- ELB（使用時のみ）


## nginx.conf

```
$ sudo vim /etc/nginx/nginx.conf
```
以下の6つを記述します。

```nginx:/etc/nginx/nginx.conf
client_max_body_size 500m;
send_timeout 6000;
fastcgi_read_timeout 6000;
proxy_connect_timeout 6000;
proxy_read_timeout    6000;
proxy_send_timeout    6000;
```

|設定  |意味|
|---|---|
| client_max_body_size |  アップロードサイズ制限|
|send_timeout | クライアント（ブラウザ）とのタイムアウトの秒数 |
| fastcgi_read_timeout |  FastCGIプロセスへデータを送信するための待ち時間|
| proxy_connect_timeout|  バックエンドサーバとの接続タイムアウト時間の指定。バックエンドサーバに接続要求を送り、n秒間接続できない場合発生。|
| proxy_read_timeout| バックエンドサーバからのデータ受信のタイムアウト秒数を指定 |
|proxy_send_timeout | バックエンドサーバへのデータ転送のタイムアウトの秒数を指定。 |

詳しくはこちら

http://vatchcjplog.blog.shinobi.jp/nginx/%E3%80%90nginx%E3%80%91%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%A2%E3%82%A6%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%83%A1%E3%83%A2




以下は挿入箇所になります。
`http`や `server`、 `location`のどこでもよいです。

```nginx:/etc/nginx/nginx.conf
 server {
        listen       80;
        server_name  test.com;
        root         /usr/share/nginx/html/test;

        location / {


            location ~ \.php$ {
                fastcgi_pass unix:/var/run/php-fpm/www.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_script_name;
                include fastcgi_params;

                client_max_body_size 500m;
                send_timeout 6000;
                fastcgi_read_timeout 6000;
                proxy_connect_timeout 6000;
                proxy_read_timeout    6000;
                proxy_send_timeout    6000;
            }
        }
    }
```

## php.ini
まずphp.iniファイルを検索します

```
$ php -i | grep php.ini

Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini

$ sudo vim /etc/php.ini
```

```php:/ect/php.ini
max_execution_time = 3000
memory_limit = 5000M
upload_max_filesize = 5000M
post_max_size = 5000M
```

|設定  |意味|
|---|---|
| max_execution_time | PHPの最大実行時間(秒) 。「0」だと無制限になります。|
|memory_limit  | PHPのメモリ使用量の上限。「-1」だと無制限になります。 |
| upload_max_filesize | 1つのファイルアップロードサイズの上限値 |
|post_max_size  | POST送信全体のデータサイズ上限 |

`post_max_size`は送信全体のデータサイズなので、`upload_max_filesize=2M`の設定時、2Mのファイルを3つ同時に送信するためには、`post_max_size=6M`以上にする必要があります。

もちろんメモリ使用量は、送信全体のデータサイズ以上の量が必要なため、以下の設定にしましょう。
`memory_limit ≧ post_max_size ≧ upload_max_filesize`

## php-fpm.conf
設定ファイルは、`/etc/php-fpm.d` 配下にあります。
私の場合は、`/etc/php-fpm.d/www.conf`でした。

```
$ sudo vim /etc/php-fpm.d/www.conf
```

```php:/etc/php-fpm.d/www.conf
;request_terminate_timeout = 0
```
|設定  |意味|
|---|---|
| request_terminate_timeout | 単一のリクエストを処理する際のタイムアウト。「0」もしくは「コメントアウト」にすると、無制限（タイムアウトされない）になります。 |

## ELB(使用時のみ)
アイドルタイムをデフォルト60秒から`4000秒`（最大）にします。
アイドルタイムが早いと、Webサーバーからのレスポンスを完了する前に、セッションを切ってしまいます。

![スクリーンショット 2021-11-11 22.37.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/0954d8f7-6c1c-8600-3d06-9bf78abbcbda.png)

## 3つのファイル修正後、再読み込みします。
`php-fpm`と`nginx`を再起動します。

```

$ sudo service php-fpm reload
$ sudo service nginx reload

もしくは↓

$ sudo systemctl restart php-fpm
$ sudo nginx -s reload

なにも表示されなければ、問題なく再起動、読み込みできている証拠です。
```




# sqlファイルのインポート再実行

再度、`サーバーから実行`をクリックします。
以下の画像のようにページに`接続が中断されました。`という表示がされますが、裏でsqlファイルがインポートしている最中です。
インポートしたDBのテーブル画面（下記の画像）に移動し、ページを更新すると、少しずつDBのテーブルやデータが増えてきます。
完了するのを待ちましょう！！


↓`サーバーから実行`後、この画面に遷移しても大丈夫です！
![スクリーンショット 2021-11-11 11.41.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/45e7371b-65b8-5acf-e768-d8bd06a0e213.png)

↓この画面で、ページを更新すると、少しずつDBのテーブルやデータが増えてくると思います。
![スクリーンショット 2021-11-11 23.12.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/d6a1c863-ded5-a785-a9ee-4fe95d88c16c.png)



# エラー集

## メモリ上限エラー
メモリ上限が少なく設定されていることが原因です。
`memory_limit`をふやしましょう。

```
Fatal error: Allowed memory size of xxxxxx bytes exhausted
```
以下のコマンドで現在のメモリ使用量設定を確認できます。

```
$ php -i | grep memory_limit
memory_limit => 128M => 128M
```

## ファイル容量の上限エラー
アップロードするファイル容量が大きいことが原因です。
上記の方法を設定し、アップロードのデータ容量の上限を増やしましょう。

```
413 Request Entity Too Large
```

## 実行時間のタイムアウト
実行時間が多くかかったことが原因です。
php.iniファイルを内の`max_execution_time`を伸ばしましょう。

```
Fatal error: Maximum execution time of 60 seconds exceeded
```

```
upstream timed out (110: Connection timed out) while reading response header from upstream
```

```
recv() failed (104: Connection reset by peer) while reading response header from upstream
```


# 参考

https://qiita.com/townsoft/items/3e2d410bbe65a364b603

http://vatchcjplog.blog.shinobi.jp/nginx/%E3%80%90nginx%E3%80%91%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%A2%E3%82%A6%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%83%A1%E3%83%A2

https://qiita.com/kinokosan/items/3aadb0bdfc6e2ae6de36

https://qiita.com/kotarella1110/items/169ddcef03983f5d64b2#elb-%E3%81%AE%E8%A8%AD%E5%AE%9A

https://arakoki70.com/?p=5657