Azureを使ってサクッと動画共有サービスを作る
YouTube等の外部Serviceを使用してもいいですが
Privateな環境で動画のアップロードをしたい場合があります
(業務利用ぐらいしか思いつきませんが…)
AzureのMediaService等を使っても良いかもしれませんが
同じくAzureのBlobStorageServiceを使用し、AzureのSDKを利用すれば
手っ取り早くプライベートな環境でビデオのアップロード&視聴が可能となります。
Angular+ASP.netで動画ファイルのアップロードと
視聴ページの作成を行ってみたいと思います
Azureの設定
CORSの設定
CORS(クロスオリジンリソース共有)を設定します。
Storageコンテナにアクセスするため、クロスドメインでアクセスできるように設定を行います。
参考にしたサイトでは、スクリプトで設定の変更を行っていますが
AzureのPortal上からも変更できるようです。
ポータルでCORSの設定を行う
1.リソースグルプでストレージアカウントを選択
2.ストレージアカウントの設定から「CORS」を選択
3.CORSの設定がないと思うので、「追加」を選択
4.上記の参考URLの内容をもとに、CORSの設定を行う
オブジェクトのAPIへのアップロード
前準備
ASP.Netはアップロードファイルの上限がデフォルト4MBとなっているので
受付可能なファイルサイズを拡張して上げる必要があります。
web.config
<system.web> <authentication mode="None" /> <compilation debug="true" targetFramework="4.5.2" /> <!--ファイルサイズの上限を変更しておく --> <httpRuntime targetFramework="4.5.2" maxRequestLength="102400" /> </system.web>
Webページからのファイルのアップロード
WebAPIへのアップロード
inputタグの[type=file accept=‘video/*’]であれば、取得対象が動画ファイルとなります。
(change)でファイル変更時のイベントを補足し、WebAPIにファイルを送る処理を実装します。
今回は横着かまして、Change即WebAPIへって感じの処理ですが
もちろん(change)でオブジェクト退避させ
Submit等のイベントを起点にAPIへおくるのが定石ですね。
<input type='file' accept='video/*' (change)="onChangeInput($event)" />
// Component private onChangeInput(el: any) { // イベントで変更されたValue=ファイルオブジェクトを取得 let file = el.target.files[0]; let formData = new FormData(); formData.append('uploadFile', file, file.name); this._webapi.putUploadFile(formData).subscribe(data => { console.log(data); }); } //---------------------------------------------------------- //webapiに送る処理 putUploadFile(formData: FormData): Observable<any> { return this.postFileData<any>("api/FileOperation", formData); }
WebApiではFormデータを送信する
//httpのPostリクエストでファイルを送信 private postFileData<T>(url: string, sendData: FormData) { return this.http .post(url, sendData, <headersContent>) .map(res => res.json()) .catch(error => { alert(error); return Observable.throw(error) }); }
WebAPIからAzureにBlobデータを登録する
POSTデータからファイルオブジェクトの取得
WebAPIではPOSTされたデータからファイル情報等を抜き出します。
public async Task<HttpResponseMessage> Post() { var response = new HttpResponseMessage(); var httpRequest = HttpContext.Current.Request; var mediaType = Request.Content.Headers.ContentType.MediaType; if (httpRequest.Files.Count > 0) { foreach (string file in httpRequest.Files) { var postedFile = httpRequest.Files[file]; /*→Azureの登録処理へ→*/ } } return response; }
コンテナにオブジェクトの登録
まずはAzureSDKを使用して、登録対象ストレージを選択(なければ作成)します。
var credentials = new StorageCredentials(<ACCOUNT_NAME>, <ACCOUNT_KEY>); var storageAccount = new CloudStorageAccount(credentials, true); var blobClient = storageAccount.CreateCloudBlobClient(); container = blobClient.GetContainerReference(<CONTAINER_NAME>); container.CreateIfNotExists();
AzureのAPIはファイルはByte引数となりますので
httpRequestのFileのStream型をByte型に変換してAzureのAPIに渡します。
[GetBlockBlobReference]でAzureにUpload出来る形にした後
[UploadFromByteArrayAsync]でAzureにアップロードします。
var sendByteData = //file.InputStreamをByte[]変換; //Blobにアップロードする対象のファイルを決定 var blob = container.GetBlockBlobReference(FILE_NAME); //メディアのタイプを決定 blob.Properties.ContentType = mediaType; //Blobにアップロード await blob.UploadFromByteArrayAsync(sendByteData, 0, sendByteData.Length);
SASを付与したURLの生成
BlobへのアクセスはShared Access Signature (SAS) で作成したURLを使用してアクセスします。
その為、作成したデータにアクセスするためのアドレスを生成します。
//コンテナ内のファイルを指定 var blob = container.GetBlockBlobReference(FILE_NAME); //SASアドレスの作成 var sas = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy() { //読取りのみ Permissions = SharedAccessBlobPermissions.Read, //1時間だけアクセス可能 SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1) }); //BlobのURIとマージしてURLを生成 var Url = string.Format("{0}{1}", blob.Uri, sas);
VideoのSrcにバインドしVideoを見れるようにする
JSONでURLを返却したら、VideoのsourceにURLをバインドします。
コストについて
日和って短い時間の動画しか上げていませんが
1週間ほど放置してもTOTALで1円以下ですんでいます。
Webサービスの一環として、かんたんでPrivateな動画共有サービスとしては導入しやすいのかなと思います