reactで作ったweb画面から音声ファイルをブラウザへアップロード さらにcloud storageにファイルをアップロードする
音声ファイルの扱い方はあまり情報がないので残しておく
環境
- node: 8.11.2
- firebase: 5.4.1
- react-cli: 1.1.4
- react-dropzone: 5.0.1
- moment: 2.22.2
- material-ui: 3.0.3
firebaseに登録、プロジェクト作成
https://firebase.google.com/docs/web/setup?hl=ja より、firebaseの登録をして、以下のようなconfigを取得する
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
};
変数にしてconfig.jsを作成しておく
./firebase/config.js
export const config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
}
実行コード
firebase関連
upload先は
config.js
storageBucket
./firebase/index.js
import firebase from 'firebase'
import { config } from './config'
export const firebaseApp = firebase.initializeApp(config)
export const audioStorage = firebaseApp.storage()
export const uploadAudioStorage = async (dataBase64, filename) => {
// 参照
let storageRef = audioStorage.ref()
// Create a reference to 'filename'
// 格納先を指定
let ref = storageRef.child(filename)
// upload base64 format
let uploadTask = ref.putString(dataBase64, 'data_url')
// アップロード完了イベントは取れるが、progress等のイベントはなぜか取れない
return uploadTask.then(async (snapshot) => {
console.log('uploaded: ', snapshot)
return await snapshot
})
}
reactコンポーネント
dropzoneでファイルをブラウザへアップロード uploadボタンをクリックするとcloud storageへアップロードする
./components/Upload.js
import React, { Component } from 'react'
import Dropzone from 'react-dropzone'
import { Button } from "@mui/material"
import moment from 'moment'
import { uploadAudioStorage } from '../firebase'
import styles from './AudioToText.css'
export default class Upload extends Component {
constructor(props) {
super(props)
this.state = {
files: [],
duration: null.
gcsPath: null
}
}
onDrop(files, rejected) {
if (rejected.length !== 0) {
console.log('rejected file ', rejected)
return
}
files.forEach((file) => {
const audio = new Audio()
audio.src = file.preview
audio.addEventListener('loadedmetadata', () => {
// 再生時間の取得
console.log('duration', audio.duration)
this.setState({
files: files,
duration: audio.duration
})
})
// ファイルの中身を読み込む
this.readFile(file)
})
}
readFile(file) {
const reader = new FileReader()
reader.onload = () => {
const fileBinary = reader.result
console.log('read file', fileBinary)
this.setState({
fileBinary: fileBinary
})
}
reader.onabort = () => console.log('file reading was aborted')
reader.onerror = () => console.log('file reading has failed')
// base64で読み込む
reader.readAsDataURL(file)
}
async onUpload() {
let state = this.state
let data = state.fileBinary
let fileName = moment().format('YYYYMMDD') + '_' + state.files[0].name
let res = await uploadAudioStorage(data, fileName)
let path = 'gs://' + res.matadata.bucket + res.metadata.fullPath
this.setState({
gcsPath: path
})
}
render() {
return (
<div className={styles.upload}>
<h4>Upload audio file to GCS</h4>
<div>
<Dropzone
className={styles.dropzone}
onDrop={this.onDrop.bind(this)}
>
<p>Dropping some file here, or click to select file to upload.</p>
</Dropzone>
<ul>
{
this.state.files.map(f => <li key={f.name}>{f.name} : {this.state.duration}s - {f.size} bytes</li>)
}
</ul>
<Button onClick={this.onUpload.bind(this)} variant="outlined" color="primary">upload</Button>
</div>
</div>
)
}
}
Updata.css
:local .upload .dropzone {
width: 300px;
height: 200px;
box-sizing: border-box;
border-width: 2px;
border-color: #666666;
border-style: dashed;
border-radius: 5px;
vertical-align: top;
margin-right: 2%;
}
こんな画面ができあがる
アップロードされたファイルは、firebaseコンソールのstorageタブから確認できる