はまったりひらめいたり…とか…

.Net系プログラムで勉強したこととか嵌ったことについて書いたりします。

Azureを使ってサクッと動画共有サービスを作る

YouTube等の外部Serviceを使用してもいいですが

Privateな環境で動画のアップロードをしたい場合があります

(業務利用ぐらいしか思いつきませんが…)

AzureのMediaService等を使っても良いかもしれませんが

同じくAzureのBlobStorageServiceを使用し、AzureのSDKを利用すれば

手っ取り早くプライベートな環境でビデオのアップロード&視聴が可能となります。

Angular+ASP.netで動画ファイルのアップロードと

視聴ページの作成を行ってみたいと思います

Azureの設定

CORSの設定

CORS(クロスオリジンリソース共有)を設定します。

Storageコンテナにアクセスするため、クロスドメインでアクセスできるように設定を行います。

参考にしたサイトでは、スクリプトで設定の変更を行っていますが

AzureのPortal上からも変更できるようです。

tech-blog.cloud-config.jp

docs.microsoft.com

ポータルでCORSの設定を行う

1.リソースグルプでストレージアカウントを選択

f:id:TakasDev:20170422012256j:plain

2.ストレージアカウントの設定から「CORS」を選択

f:id:TakasDev:20170422012321j:plain

3.CORSの設定がないと思うので、「追加」を選択

f:id:TakasDev:20170422012349j:plain

4.上記の参考URLの内容をもとに、CORSの設定を行う

f:id:TakasDev:20170422012433j:plain

オブジェクトのAPIへのアップロード

前準備

ASP.Netはアップロードファイルの上限がデフォルト4MBとなっているので

受付可能なファイルサイズを拡張して上げる必要があります。

tarcvf.blogspot.jp

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();

gooner.hateblo.jp

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を使用してアクセスします。

その為、作成したデータにアクセスするためのアドレスを生成します。

stackoverflow.com

//コンテナ内のファイルを指定
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をバインドします。

stackoverflow.com

コストについて

日和って短い時間の動画しか上げていませんが

1週間ほど放置してもTOTALで1円以下ですんでいます。

Webサービスの一環として、かんたんでPrivateな動画共有サービスとしては導入しやすいのかなと思います

f:id:TakasDev:20170422014501p:plain