PHP
 Computer >> コンピューター >  >> プログラミング >> PHP

PHPで500MBを超える大容量ファイルをアップロードする方法を徹底解説

PHPで大容量ファイルをアップロードするには、主に2つの方法があります。

  • php.iniファイルの設定を変更する方法:upload_max_filesizeなどの上限値を引き上げます。
  • ファイルのチャンク(分割)アップロードを実装する方法:ファイルを小さな断片に分けて送信し、アップロード完了後にそれらを結合します。

それぞれの方法について、具体的な手順を見ていきましょう。

方法1:php.iniの設定を変更してアップロード上限を引き上げる

まずはphp.iniファイルを以下のように編集します。

upload_max_filesize = 50M
post_max_size = 50M
max_input_time = 300
max_execution_time = 300

ただし、この方法はサーバー全体の設定に影響し、同じサーバー上で動作している他のプロジェクトにも影響を与える可能性があるため、注意が必要です。

.htaccessファイルで設定する

php.iniを直接編集できない環境では、.htaccessファイルに以下のように記述することもできます。

php_value upload_max_filesize 50M
php_value post_max_size 50M
php_value max_input_time 300
php_value max_execution_time 300

スクリプト内でini_set()を使って設定する

PHPコード内で動的に設定を変更したい場合は、ini_set()関数を使用します。

<?php
    // アップロード制限を変更
    ini_set('upload_max_filesize', '50M');
    ini_set('post_max_size', '50M');
    ini_set('max_input_time', 300);
    ini_set('max_execution_time', 300);
    // 保存先フォルダを指定
    $source = $_FILES["file-upload"]["tmp_name"];
    $destination = $_FILES["file-upload"]["name"];
    // アップロードされたファイルを保存先へ移動
    move_uploaded_file($source, $destination);
?>

なお、upload_max_filesizeなど一部のディレクティブはPHP_INI_PERDIRまたはPHP_INI_SYSTEMに分類されているため、ini_set()では変更できない場合があります。その場合はphp.iniや.htaccessでの設定変更が必要です。

方法2:チャンク(分割)アップロードを実装する

もうひとつの方法は、大きなファイルを小さな部分に分割して順次アップロードし、最後にそれらを結合する「チャンクアップロード」です。この方式では、「Plupload」などのライブラリをダウンロードして利用すると便利です。

以下はサーバー側でチャンクを受け取り、結合するPHPの実装例です。

<?php
    // レスポンス用の関数
    function verbose($ok=1,$info=""){
        // アップロード失敗時は400エラーを返す
        if ($ok==0) { http_response_code(400); }
        die(json_encode(["ok"=>$ok, "info"=>$info]));
    }
    // 無効なアップロードのチェック
    if (empty($_FILES) || $_FILES['file']['error']) {
        verbose(0, "Failed to move uploaded file.");
    }
    // アップロード先のパス
    $filePath = __DIR__ . DIRECTORY_SEPARATOR . "uploads";
    if (!file_exists($filePath)) {
        if (!mkdir($filePath, 0777, true)) {
            verbose(0, "Failed to create $filePath");
        }
    }
    $fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : $_FILES["file"]["name"];
    $filePath = $filePath . DIRECTORY_SEPARATOR . $fileName;
    // チャンクの処理
    $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
    $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;
    $out = @fopen("{$filePath}.part", $chunk == 0 ? "wb" : "ab");
    if ($out) {
        $in = @fopen($_FILES['file']['tmp_name'], "rb");
        if ($in) {
            while ($buff = fread($in, 4096)) { fwrite($out, $buff); }
        } else {
            verbose(0, "Failed to open input stream");
        }
        @fclose($in);
        @fclose($out);
        @unlink($_FILES['file']['tmp_name']);
    } else {
        verbose(0, "Failed to open output stream");
    }
    // ファイルのアップロードが完了したか確認
    if (!$chunks || $chunk == $chunks - 1) {
        rename("{$filePath}.part", $filePath);
    }
    verbose(1, "Upload OK");
?>

この実装では、各チャンクを一時ファイル(.part)に追記していき、すべてのチャンクが揃った時点で正式なファイル名にリネームします。これにより、500MBを超えるような大容量ファイルでも、サーバーのメモリやタイムアウト制限に引っかかることなく安定してアップロードできます。

まとめ

手軽なのはphp.iniなどの設定変更ですが、サーバー全体への影響を考えると、チャンクアップロードの方が安全かつ確実です。特に動画やバックアップデータなど数百MB規模のファイルを扱う場合は、Pluploadのようなライブラリを活用した分割アップロードの導入を検討しましょう。

  1. インターネットで大容量ファイルを送信する方法|無料で安全に送れる5つのサービス

    近年、インターネットを通じて大容量ファイルを送信するニーズは急速に高まっています。本記事では、手間をかけずに大容量ファイルを安全に転送できる、最も信頼性の高い方法をご紹介します。 GmailやOutlookといった標準的なメールサービスでは、25MBを超えるファイルを添付して送信することができません。そのため、大容量ファイルを送りたい場合は、別の手段を利用する必要があります。ここでは、セキュリティを確保しながら大容量ファイルを簡単に送れる方法を厳選して解説します。 大容量ファイルを無料で送信・転送する方法 まずはファイルを圧縮しよう: 大容量ファイルを送信する前に、圧縮ソフトを使ってファイルサ

  2. WordPressのwp-config.phpファイルを保護する方法を徹底解説

    ハッカーの視点で考えてみてください。何千ものWebサイトが利用しているプラットフォームに侵入したり、複数のサイトに対してブルートフォース攻撃を仕掛けたりするのは、彼らにとって魅力的な標的です。WP-Scannerのようなオープンソースツールが出回っている現在、初心者レベルの攻撃者でも、プロフェッショナルなWordPressサイトに侵入し、悪夢のような被害をもたらすことが可能になっています。 その中でもwp-config.phpは、サイトの運命を左右する最重要ファイルの一つです。このファイルが漏洩すれば、サイト全体が危険にさらされます。本記事では、wp-config.phpファイルを安全に保護す