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

Angularや.NETやAzureやその他色々。

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