Azure Blobを分割してアップロードしてみた
Azureにアップロードする際にどうも一括アップロードの容量制限があるのでそれを対応してみたお話
ついでにPHPの容量制限も上げたくなかった><
ざっくり流れ
フロント => PHP => Azure
- フロントからファイルアップロードして分割で(jQuery-File-Uploadを利用
- PHPで分割されたファイルを受け取ってtmpフォルダに突っ込む
- フロントからデータの転送がすべて終わったら、PHPからAzureに送るやつを呼ぶ
- PHPからAzureに分割してデータを送って最後に1まとめにして完了!(azure-storage-php
フロント
※めちゃくちゃパクりましたm(_ _)m
jQuery-File-Upload サンプル
https://qiita.com/shiccocsan/items/074e03c5f41f986afc29
maxChunkSize と unique_keyを付けてるところが重要
unique_keyはPHPで作ってAPIでもらう流れ作ったほうが安全そう
<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
/**
* 分割アップロードの処理
**/
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のデータ制限を回避しつつ
- アップロードができる!
適当にソース書き換えてアップしたので適宜書き換えてください!