この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、リサリサです。
AWS Amplify for JavaScript がストレージのリジューム可能なファイルアップロードをサポートしたので触ってみました。
※フロント全然分からない人間が書いています。vue.js 今回初めて触りました…。なので、ソースコード等、細かい部分はあまり当てにしないで頂けると幸いです。あくまでアップデートした機能の動きの参考と見て頂ければと思います。
追加された事
AWS Amplify for JavaScript がストレージのリジューム可能なファイルアップロードをサポート
AWS Amplify for JavaScript は、Amplify ストレージカテゴリ経由で Simple Storage Service(Amazon S3) にファイルをアップロードする際の一時停止、再開、キャンセルのアクションに対応しました。Amplify はユースケース指向の UI コンポーネント、ライブラリ、コマンドラインツールのセットを提供し、フロントエンドのウェブやモバイルのデベロッパーがアプリケーションのための AWS クラウドバックエンドを簡単に構築できるようにします。
S3 アップロードの一時停止、再開、キャンセルが出来るようになったようです。また、途中で通信が途切れた場合なども、途中から再開が出来るようです。
const upload = Storage.put(file.name, file, {
resumable: true,
});
//一時停止
upload.pause();
//再開
upload.resume();
//キャンセル
Storage.cancel(upload);
やってみた
S3 にアップロードできるアプリを作る
以下ブログを元にS3にアップロードができるアプリケーションをまず作ってみます。
基本的にはブログ通りに進めるのですが、少し古い記事で、サンプルソースもあまり更新がされておらずライブラリが古めです。サンプルソースのままだと amplify のバージョンが古くて今回追加されたメソッドが使えません。なので、試される方は git からcloneした後、package.json の dependencies を以下に書き換えてから「yarn install」してみてください。
"dependencies": {
"@vue/cli-plugin-unit-jest": "^3.2.0",
"@vue/cli-service": "^3.2.0",
"@vue/test-utils": "^1.0.0-beta.27",
"aws-amplify": "^4.3.4",
"aws-amplify-vue": "^2.1.5",
"aws-sdk": "^2.1022.0",
"e": "0.0.4",
"element-ui": "^2.15.6",
"fsts": "^0.0.39",
"vue": "^2.5.16",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
ブログ通りに進め、ユーザー作成までするとこのような画面になります。
S3 アップロード、ダウンロード、削除ができるアプリが完成です。
一時停止、再開、キャンセルの機能を追加
ここに、一時停止、再開、キャンセルの機能を追加して、動作確認してみます。
src/Home.vue
を以下のように変更します。
pause、resume、cancel、というボタンを追加して、それぞれのメソッドを追加しています。また、「progressCallback」で、どこまで送信したかを監視していきます。
<template>
<div class="container shifted">
<h1 class="h1">
S3 Objects
</h1>
<el-button>
<label for="file">
Upload
<input type="file" @change="upload" id="file" style="display:none;">
</label>
</el-button>
<el-button @click="pause">pause</el-button>
<el-button @click="resume">resume</el-button>
<el-button @click="cancel">cancel</el-button>
<el-button @click="refresh" class="el-icon-refresh-left"></el-button>
<el-table :data="s3Data" style="width: 100%">
<el-table-column prop="key" label="Key" sortable>
</el-table-column>
<el-table-column prop='lastModified' label="LastModified" sortable>
</el-table-column>
<el-table-column prop="size" label="Size" sortable>
</el-table-column>
<el-table-column>
<template slot-scope="scope">
<el-button @click="download(scope.row)">Download</el-button>
<el-button type="danger" @click="openDeleteDialog(scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog title="Delete objects" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<span>{{ deleteObject }} Objects will be deleted</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="deleteOK()">Confirm</el-button>
</span>
</el-dialog>
</div>
</template></pre>
<pre><script>
import Vue from 'vue'
import Amplify, { API,Storage } from 'aws-amplify';
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/en'
Vue.use(ElementUI, { locale })
export default {
name: 'Home',
data () {
return {
s3Data: [],
dialogVisible: false,
selectedRow: "",
deleteObject: "",
uploadObject:""
}
},
created () {
this.refresh()
},
methods: {
refresh () {
Storage.list('')
.then(result => this.s3Data = JSON.parse(JSON.stringify(result)))
.catch(err => console.log(err));
},
// 一時停止
pause(){
console.log(`★${new Date().toLocaleString()}_転送中断`) this.uploadObject.pause()
},
// 再開
resume(){
console.log(`★${new Date().toLocaleString()}_転送再開`)
this.uploadObject.resume()
},
// 中断
cancel(){
console.log(`★${new Date().toLocaleString()}_転送中止`)
Storage.cancel(this.uploadObject);
},
upload(e) {
var files = e.target.files || e.dataTransfer.files
console.log(`★${new Date().toLocaleString()}_転送開始`)
this.uploadObject =
Storage.put(files[0].name, files[0],{
resumable: true,
progressCallback: (progress) => {
console.log(`★${new Date().toLocaleString()}_${progress.loaded}/${progress.total}送信済...`)
if(progress.loaded == progress.total){
console.log(`★${new Date().toLocaleString()}_転送終了`)
}
}
})
},
download (row) {
Storage.get(row['key'], { download: true })
.then(result => {
console.log(result)
const url = URL.createObjectURL(new Blob([result.Body]));
const link = document.createElement('a')
link.href = url
link.download = row['key']
console.log(link)
link.click()
})
.catch(err => console.log(err));
},
openDeleteDialog(row) {
this.selectedRow = row;
console.log(row)
this.deleteObject = row['key'];
this.dialogVisible = true
},
deleteOK () {
this.dialogVisible = false
Storage.remove(this.selectedRow['key'])
.then(result => {
console.log(result)
this.refresh()
}
)
.catch(err => console.log(err));
},
handleClose(done) {
this.$confirm('Are you sure to close this dialog?')
.then(_ => {
done();
})
.catch(_ => {});
}
}
}
</script>
<style>
label {
color: #606266;
background-color:white;
padding: 10px;
}
</style></pre>
<pre>
画面はこんな感じになりました。
動かしてみる
Chrome の F12 でログを確認しながらそれぞれの動きを確認してみます。デバッグログがたくさん出るので、「★」でフィルターして確認してます。
一時停止、再開、キャンセル
「Upload」からアップロードを始めると、転送が始まります。監視ログでどのくらい転送が進んだかが分かります。
「pause」で中断すると、転送も中断し監視ログも止まりました。「resume」から再開をすると「120586240/1073741824」となり、途中から再開されているのがかわります。
★2021/11/8 16:56:14_転送開始
★2021/11/8 16:56:14_5242880/1073741824送信済...
★2021/11/8 16:56:15_10485760/1073741824送信済...
★2021/11/8 16:56:15_15728640/1073741824送信済...
~略~
★2021/11/8 16:56:16_104857600/1073741824送信済...
★2021/11/8 16:56:16_110100480/1073741824送信済...
★2021/11/8 16:56:17_115343360/1073741824送信済...
★2021/11/8 16:56:17_転送中断
★2021/11/8 16:56:20_転送再開
★2021/11/8 16:56:20_120586240/1073741824送信済...
★2021/11/8 16:56:20_125829120/1073741824送信済...
★2021/11/8 16:56:20_131072000/1073741824送信済...
~略~
★2021/11/8 16:56:22_214958080/1073741824送信済...
★2021/11/8 16:56:22_220200960/1073741824送信済...
★2021/11/8 16:56:22_225443840/1073741824送信済...
★2021/11/8 16:56:22_転送中止
強制終了からの再アップロード
ある程度送信した後、画面をリフレッシュして、通信を強制切断してみます。その後、「Upload」から再度アップロードボタンからアップロードをしてみます。
最初から「466616320/1073741824」なので、最初に送信した分は無駄にならず、途中から再開されているのが分かります。
★2021/11/8 17:06:50_転送開始
★2021/11/8 17:06:50_466616320/1073741824送信済...
★2021/11/8 17:06:51_471859200/1073741824送信済...
★2021/11/8 17:06:51_477102080/1073741824送信済...
★2021/11/8 17:06:51_482344960/1073741824送信済...
★2021/11/8 17:06:51_487587840/1073741824送信済...
最後に
amplify 初めて触ったのですが、あっという間にリソースが作成されて感動しました。普段触らない機能を触ると楽しいですね。どなたかのお役に立てれば幸いです。
参考
[1]ストレージ-ファイルのアップロード-JavaScript-AWSAmplify Docs
[2]AWS Amplify for JavaScript がストレージのリジューム可能なファイルアップロードをサポート