Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@tenda_chi

【PHP】大きいサイズファイルのHTTPアップロード

1.通常のやり方

  1. php設定値を大きく設定して
    • upload_max_filesize = 500M
    • post_max_size = 500M
    • max_input_time = 300
    • max_execution_time = 300

2.Client-Side HTML.
enctype="multipart/form-data"とする。

<!doctype html>
<html lang="ja">
<head>

   <meta charset="utf-8">
   <title>test upload</title>
</head>
<body>
<form method="post" action="upload.php" enctype="multipart/form-data">
ファイル:<input type="file" name="myfile"><br>
<input type="submit" value="upload">
</form>
</body>
</html>

3.Server-Side PHP

if(is_uploaded_file($_FILES['myfile']['tmp_name'])){
    if(move_uploaded_file($_FILES['myfile']['tmp_name'],"./".$_FILES['myfile']['name'])){
        echo "upload successed.";

    }else{
        echo "error save file.";
    }

}else{
    echo "error upload file.";
}

//laravel
$dir_path = storage_path('app/debug');
$file = Request::file('myfile');
$name = $file->getClientOriginalName();
$move = $file->move(dir_path,$name);

通常やり方の問題点

  • PHPの色んな設定値を気にしないといけない。
  • 場合によってHTTPサーバーの設定値も調整する必要がある。
    • Nginx: client_max_body_size 100m;
    • Tomcat: maxPostSize="10485760"
    • Apache: LimitRequestBody=0
  • ファイルサイズが数GBを超えると何れ何処の壁とぶつかる。

2.ファイルを分割して複数回リクエストでアップロードする方法

TUS resumable upload protocol

https://tus.io/
ファイルアップロード途中でブラウザを再読み込みするなどして、強制中断した後に、同じファイルをアップロードすると、中断時点からアップロード処理を再開することができます。

Demo

Tusとは

tusは、再開可能なファイルのアップロードを簡単に使用でき、広く利用できるようにすることを目的としたプロジェクトです。
このプロジェクトの最も興味深い部分は、プロトコル仕様と多くの自由に利用可能なクライアントとサーバーの実装です。

主な特徴

  • HTTP-based
    HTTPプロトコルの上にレイヤーとして構築されたtusは、既存のライブラリ、プロキシ、ファイアウォールを使用してアプリケーションに簡単に統合でき、任意のWebサイトから直接使用できます。

  • Production-ready
    tusはプロダクション環境にも安心的に利用可能です。何度も改善され、Vimeo、Google、その他の複数の有名企業で働く人々から貴重なフィードバックを受けています。

  • Open source
    MITライセンスでの利用が可能。https://github.com/tus

  • Minimalistic design...
    ClientとServerに少ないコードを実装をするだけで利用可能。tusは、すべての人にシンプルさ、迅速な開発、イテレーション速度を提供します。

  • ... yet still extensible
    tusには、並列アップロードやチェックサムと有効期限などの追加機能を導入する拡張機能のかなりのリストがあります。これらはすべて、好みに応じて実装できます。

  • Community-owned
    このプロトコルのオープンでアクセス可能な進化を信じています。 tusの開始以降のどの段階でも、フィードバックは高く評価され、統合されています。あなたの貢献も楽しみにしています。

Server-Side PHP

1.Installation
$ composer require ankitpokhrel/tus-php

2.Laravel Integration
新しいserviceProviderを作成する。

namespace App\Providers;  
use TusPhp\Tus\Server as TusServer; 
use Illuminate\Support\ServiceProvider;  
class TusServiceProvider extends ServiceProvider {     
  // ...      
  /**      
   * Register the application services.
   *       
   * @return void      
   */     
   public function register()
   {
     $this->app->singleton('tus-server', function ($app) {
         $server = new TusServer('redis');
         $server->setApiPath('/tus') // tus server endpoint.
             ->setUploadDir(storage_path('app/public/uploads')); // uploads dir.
          return $server;
     });
   }
   // ...
 }

Routing設定

Route::any('/tus/{any?}', function () {
  $response = app('tus-server')->serve();
  return $response->send(); 
})->where('any', '.*');

CSRF validationを除外する

// ... 
class VerifyCsrfToken extends BaseVerifier {
  // ...
  protected $except = [
     '/tus',
     '/tus/*',
  ];
}

Client-Side

1.Vue 版
$ npm install tus-js-client

  <template>
  ... ...
    <input type="file" name="largefile" @change="fileSelected">
    <button-submit class="btn btn-adn" :onclick="tusUpload"><span>ファイルアップロード</span></button-submit>
  ... ...
  </template>
  <script>
    import * as Tus from 'tus-js-client'
    export default {
      data: function () {
          return {
              fileInfo: '',
          }
      },
      methods: {
          fileSelected: function (e) {
              this.fileInfo = e.target.files[0];
          },
          tusUpload: function (e) {
            e.preventDefault();
              return new Promise((resolve) => {
                  // Get the selected file from the input element
                  var file = this.fileInfo;
                   // Create a new tus upload
                  var upload = new Tus.Upload(file, {
                      endpoint: "/tus",
                      retryDelays: [0, 3000, 5000, 10000, 20000],
                      chunkSize: 1024 ** 1024 ** 1,
                      metadata: {
                          filename: file.name,
                          filetype: file.type
                      },
                      onError: function(error) {
                          console.log("Failed because: " + error);
                      },
                      onProgress: function(bytesUploaded, bytesTotal) {
                          var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
                          console.log(bytesUploaded, bytesTotal, percentage + "%");
                      },
                      onSuccess: function() {
                          console.log("Download %s from %s", upload.file.name, upload.url);
                      }
                  })
                   // Start the upload
                  upload.start();
                  resolve();
              });
          }
      }
  }

2.JS版

  input.addEventListener("change", function(e) {
    // Get the selected file from the input element
    var file = e.target.files[0]
    // Create a new tus upload
    var upload = new tus.Upload(file, {
      endpoint: "/tus",
      retryDelays: [0, 3000, 5000, 10000, 20000],
      metadata: {
          filename: file.name,
          filetype: file.type
      },
      onError: function(error) {
          console.log("Failed because: " + error)
      },
      onProgress: function(bytesUploaded, bytesTotal) {
          var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2)
          console.log(bytesUploaded, bytesTotal, percentage + "%")
      },
      onSuccess: function() {
          console.log("Download %s from %s", upload.file.name, upload.url)
      }
    })
    // Start the upload
    upload.start()
  })

3.進捗を見える化
onProgressのeventを利用して画面側にプログレスバーの表示は可能です。

参考URL

https://tus.io/
https://github.com/ankitpokhrel/tus-php
https://github.com/tus/tus-js-client

以上

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
tenda
『働き方改革』があらゆる企業で求められる20年以上も前から、多様な側面から企業改革を行うための『ワークスタイル変革』のソリューションを提供しています。 お客さまの課題解決のために、技術・営業・広報・マーケティング・コールセンターが連携して活動している、ITでお客さまの利益創造に貢献する会社です。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?