Golangファイルアップロードサービス

Golangでのファイルアップロードサービスのサーバー側の開発中に、別のアプリケーションが生まれました-pavo。 アプリケーションのタスクには、一度に1つまたは複数のファイル全体のダウンロード、ピース単位のファイルダウンロード(チャンクアップロード)、イメージコンバーターが含まれます。 multipart/form-data



を介してデータの読み込みを実装し、リクエスト本文でファイルをバイナリ形式でダウンロードします。 実稼働環境で作業するには、nginxを使用して、低速接続を許可および処理します。 クライアントライブラリとして、 jQuery File Uploaderを使用できます。



設置



コンパイラーのインストール


アプリケーションをインストールするには、Golangコンパイラが必要です。 インストール手順は、 公式Webサイトで見つけることができます。 また環境変数$GOPATH



設定する必要があります。



MacOSでこれを行う方法の例:

  1. コンパイラをインストールします。



     $ brew install go $ mkdir $HOME/go
          
          



  2. ユーザープロファイルを編集して、環境変数を構成します。



     # Add this line in your .zshrc or .bash_profile export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin
          
          







バージョン管理システムをインストールする


コードを含むコミュニティリポジトリは集中化されていません。 さまざまなバージョン管理システムが使用されます。



MacOSのインストール例:



 $ brew install git mercurial svn bazaar
      
      







ImageMagickをインストールする


ImageMagickは 、画像をサーバーに変換するために使用されます。



 $ brew install imagemagick
      
      







アプリケーションのインストール


最初のインストールで、コンソールでコマンドを実行します。



 $ go get github.com/kavkaz/pavo
      
      





アプリケーションと依存ライブラリを更新する場合:



 $ go get -u github.com/kavkaz/pavo/...
      
      







クイックスタート



基本的な例でアプリケーションがどのように機能するかを確認するには、コンソールでコマンドを実行します。

 $ pavo --storage=$GOPATH/src/github.com/kavkaz/pavo/dummy/root_storage
      
      





したがって、 --storage



オプションで指定されたディレクトリ内のルートディレクトリを使用してアプリケーションを--storage



ました。 基本的な例のあるサービスは、 localhost:9073/example/jfu-basic.html



localhost:9073/example/jfu-basic.html



別のホストとポートを指定するには、コンソールオプション--host



を使用します。



プロトコルの詳細



イメージをロードするときの典型的なサーバーの応答:



 { "files": [ { "dir": "/image/2014/6s/1c5cnx", "name": "original_user_filename.jpg", "type": "image", "versions": { "original": { "filename": "original-1qeh.jpg", "height": 420, "size": 28057, "url": "/image/2014/6s/1c5cnx/original-1qeh.jpg", "width": 300 }, "thumbnail": { "filename": "thumbnail-1qef.jpg", "height": 90, "size": 3566, "url": "/image/2014/6s/1c5cnx/thumbnail-1qef.jpg", "width": 120 } } } ], "status": "ok" }
      
      





サーバーにファイルをアップロードする最も一般的な方法は、フォームを使用することです。 この場合、リクエストは次のように表示されます。

 POST /files HTTP/1.1 Content-Length: 21929 Content-Type: multipart/form-data; boundary=----5XhQf4IXV9Q26uHM ------5XhQf4IXV9Q26uHM Content-Disposition: form-data; name="files[]"; filename="pic.jpg" Content-Type: image/jpeg ...bytes...
      
      





Content-Type



ヘッダーでは、 boundary



値が渡されます。これは、リクエスト本文の値を分離するのに役立ちます。 したがって、1つの要求で複数のファイルを転送できます。 jQuery File Uploadには、複数のファイルのアップロードに対応するオプションがあります。



最新のアプローチでは、クライアント側でXHRリクエストを使用してバイナリデータを送信できます。 サーバーに表示されるリクエストは次のとおりです。

 POST /files HTTP/1.1 Content-Length: 21744 Content-Disposition: attachment; filename="pic.jpg" ...bytes...
      
      





この方法では、1つのリクエストで1つのファイルのみを転送できます。その名前はContent-Disposition



ヘッダーで使用できます。



クライアント側で大きなファイルをロードするために、ソースファイルの一部でリクエストのパケットが形成されます。 リクエストの例:

 POST /files HTTP/1.1 Content-Length: 10240 Content-Range: bytes 0-10239/36431 Content-Disposition: attachment; filename="pic.jpg" Cookie:pavo=377cb76c-2538-40d3-a3d0-13d86d206ba7 ...bytes...
      
      





ソースファイル名とpavoキーによるcookie値は、オリジナルのロードされた部分を持つ中間ファイルを識別するために使用されます。 Content-Range



ヘッダーには、クライアントがファイルのどの部分を配信しているか、元のファイルのサイズについての情報が含まれています。 最後のピースがロードされると、サーバーはダウンロード手順を完了し、受信したファイルとそのバージョンに関するデータを含む応答を生成します。



アプリケーションコード



アプリケーションはGolangで書かれています。 Ginは Webフレームワークとして使用されます。 コードは2つのパッケージ( アップロード添付ファイル )とメインアプリケーション(実行可能ファイル)に分割されます。 アップロードパッケージは、ソースファイルまたはファイルの一部をダウンロードする役割を果たします。 添付ファイルパッケージは、ファイルとそのバージョンを保存する最終ディレクトリを作成し、画像を変換し、データを生成します。 メインアプリケーションはWebサーバーを起動し、コントローラーの役割を実装します。



テストの小さな例のソースコードはgithubで入手できます。



アプリケーションオプション



アプリケーションには、起動オプション--host



および--storage



ます。 host:port



を示しhost:port



Webサーバーとストアのルートディレクトリをそれぞれ起動するhost:port







アプリケーションは、アドレス/files



へのすべてのダウンロード要求を受け入れ/files



。 query_stringパラメーターのconverts



は、画像の変換パラメーターを渡すことができます。 例:



 POST /files?converts={"pic":"400x300"}
      
      





すべてのファイルについて、デフォルトのバージョンはoriginalに設定されてます。 画像の場合、値が120x90



サムネイル 120x90



ます。



本番環境



実稼働環境で作業するには、 nginx Webサーバーを使用することをお勧めします。 Webサーバーのタスクには、クライアントからの要求の受信、本文の一時ファイルへの書き込み、メインアプリケーションでの要求の承認、元の要求のヘッダーのpavoアプリケーションへの送信が含まれます。



推奨されるnginx構成:



 server { listen 80; server_name pavo.local; access_log /usr/local/var/log/nginx/pavo/access.log; error_log /usr/local/var/log/nginx/pavo/error.log notice; location /auth { internal; proxy_method GET; proxy_set_header Content-Length ""; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_request_body off; proxy_pass http://localhost:3000/auth/url/in/your/app; client_max_body_size 0; } location /files { auth_request /auth; client_body_temp_path /tmp; client_body_in_file_only on; client_body_buffer_size 521K; client_max_body_size 10G; proxy_pass_request_headers on; proxy_set_header X-FILE $request_body_file; proxy_pass_request_body off; proxy_set_header Content-Length 0; proxy_pass http://127.0.0.1:9073; } location / { root /Path/To/Root/Of/Storage; } }
      
      







要求はクライアントからWebサーバーに送られます。 Nginxはリクエスト全体の受信を待機しています(この機能では、アプリケーションサーバーへのプロキシを使用した本格的なプログレスバーを実装できません)。 要求を受信した後、本文はclient_body_temp_path



オプションで指定されたディレクトリ内の一時ファイルに書き込まれます。



pavoアプリケーションサーバーにリクエストを送信する前に、認証が実行されます。 これを行うには、 ngx_http_auth_request_moduleモジュールを使用します。 location /auth



に対してサブクエリが作成され、元のリクエストのヘッダーがメインアプリケーションのサーバーにプロキシされます。 認証に成功した場合、サーバーは応答ステータスコード200



空の本体を返す必要があります。



次に、元のリクエストのヘッダーであるX-File



キーに新しいペアが追加され、値はリクエスト本文を含む一時ファイルへのパスになります。 その後のみ、結果のリクエスト(ヘッダーと空のボディ)がpavoアプリケーションに送信されます。 要求を処理してファイルを保存し、ダウンロードしたファイルに関するデータをJSON形式で返します。



おわりに



このサービスは、ファイルのダウンロードと配布、画像、ビデオ、およびオーディオの変換の役割を担うWebプロジェクトのインフラストラクチャ内のスタンドアロンアプリケーションとして考案されました。 HTTP Json APIを介したインターフェース。



更新: nginx構成のプロキシリクエストヘッダー設定が修正されました。



All Articles