Azure Blob(動画ファイル)を分割アップロードしてみた

# Azure Blobを分割してアップロードしてみた

Azureにアップロードする際にどうも一括アップロードの容量制限があるのでそれを対応してみたお話
ついでにPHPの容量制限も上げたくなかった＞＜

## ざっくり流れ
`フロント => PHP => Azure`

- フロントからファイルアップロードして分割で(jQuery-File-Uploadを利用
- PHPで分割されたファイルを受け取ってtmpフォルダに突っ込む
- フロントからデータの転送がすべて終わったら、PHPからAzureに送るやつを呼ぶ
- PHPからAzureに分割してデータを送って最後に１まとめにして完了！（azure-storage-php


## フロント

※めちゃくちゃパクりましたm(_ _)m
jQuery-File-Upload サンプル
https://qiita.com/shiccocsan/items/074e03c5f41f986afc29

maxChunkSize と unique_keyを付けてるところが重要
unique_keyはPHPで作ってAPIでもらう流れ作ったほうが安全そう

```html
<script src="file_upload/js/vendor/jquery.ui.widget.js"></script>
<script src="file_upload/js/jquery.iframe-transport.js"></script>
<script src="file_upload/js/jquery.fileupload.js"></script>
<link rel="stylesheet" href="file_upload/css/jquery.fileupload.css" />

<span class="btn btn-success fileinput-button">
        <i class="glyphicon glyphicon-plus"></i>
        <span>Select files...</span>
        <input id="fileupload" type="file" name="files[]" multiple>
    </span>
<br>
<br>
<!-- The global progress bar -->
<div id="progress" class="progress">
    <div class="progress-bar progress-bar-success"></div>
</div>

<script>
        $(function () {
            'use strict';

            let url = "/upload"; // 要url変更
            let commit_url = "/commit"; // 要url変更
            $('#fileupload').fileupload({
                url: url,
                dataType: 'json',
                maxChunkSize: 5242880, // ここを指定して分割アップロードさせる5M毎
                add: function (e, data) {
                    let unique_key = Math.floor(Math.random() * 1000);
                    data.unique_key = unique_key;
                    data.submit();
                },
                done: function (e, data) {
                    $.each(data.result.files, function (index, file) {
                        $('<p/>').text(file.name).appendTo('#files');
                    });
                    // 全部送信し終わったら、Azureにアップロードする処理を呼ぶ
                    $.ajax(commit_url, {
                        type: "POST",
                        data: {'file_name': data.files[0].unique_key},
                    })
                },
                progressall: function (e, data) {
                    var progress = parseInt(data.loaded / data.total * 100, 10);
                    $('#progress .progress-bar').css(
                            'width',
                            progress + '%'
                    );
                }
            }).prop('disabled', !$.support.fileInput)
                    .parent().addClass($.support.fileInput ? undefined : 'disabled');
        });
</script>
```

## バックエンド

Phalconベースなのでメソッド適当に置き換えてくだし><

PHP Azureライブラリ
https://github.com/Azure/azure-storage-php

```php

    /**
    * 分割アップロードの処理
    **/
    public function uploadAction()
    {
        $request = new Request();
        if ($request->hasFiles() == true) {
            foreach ($this->request->getUploadedFiles() as $file) {
                // tmpフォルダに連番を付けて置く
                $tmpDir = "/tmp/" . $request->get('unique_key');
                $count = $this->getFileCount($tmpDir);
                $file->moveTo($tmpDir . '/' . $count);
            }
        }
    }

    /**
    * 分割アップロードが終わった後にAzureに送る処理
    **/
    public function commitAction()
    {
        $request = new Request();
        $tmpDir = '/tmp/' . $request->get('unique_key');
        $blobName = 'なんか名前';

        $connectionString = 'DefaultEndpointsProtocol=https;AccountName=hogehoge;AccountKey=hogehgoeghoege==;';
        $containerName = "hogehoge";

        $blobClient = BlobRestProxy::createBlobService($connectionString);

        $blockId = 1;
        $blockList = new BlockList();
        $count = $this->getFileCount($tmpDir);
        foreach (range(0, $count - 1) as $i)
        {
            $file_path = $tmpDir . '/' . $i;
            $content = file_get_contents($file_path);

            //upload the block
            $blobClient->createBlobBlock($containerName, $blobName, md5($blockId),$content);
            $blockList->addLatestEntry(md5($blockId)); //you need to maintain a list of all the blockIds that are a part of this blob
            $blockId++;
        }

        $options = new CommitBlobBlocksOptions();
        // $options->setContentType('video/mp4'); // 必要であれば適宜
        $blobClient->commitBlobBlocks(
            $containerName,
            $blobName,
            $blockList->getEntries(),
            $options
        ); //Merge all the blockIds to form the blob.

        return $blobClient->getBlobUrl($containerName, $blobName);
    }
```


こんなかんじですると
- PHPのデータ容量をあげずに
- Azureのデータ制限を回避しつつ
- アップロードができる！

適当にソース書き換えてアップしたので適宜書き換えてください！