🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

3回答

4413閲覧

base64(Data URL)から画像データを復元したい

matsuo_basho

総合スコア88

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

3クリップ

投稿2021/03/03 14:50

編集2021/03/03 15:43

いつもお世話になっております。

現在Nuxtで画像アップロード機能を実装しているのですが、
画像を選択直後にプレビュー表示させるためにreadAsDataURL()を用いて
base64(厳密にはData URL)に変換し、HMTLの <img src="〇〇"> で表示をしています。

ここまでは想定通りの動きをしてくれているのですが、
バックエンドに画像をアップする際にはbase64のままアップすると
当然ですがDB内にbase64のデータがそのまま入ってしまいます。

これで良いと言えば良いのですが、
できればDBにはファイルまでのパスを保存し、画像データは専用のフォルダに格納をしたいと思っています。

そこで、フロント側で画像データをアップする前にbase64(厳密にはData URL)を画像データに戻してからアップしようとしているのですが、この戻す作業ができません。
(下記pages/upload.vueupload()に該当の記述があります)

以下はフロント側のコードですが、
日本語を含んでいないにもかかわらず文字化けを起こしてしまうのですが、
どこが良くないのでしょうか。もしわかる方がいらっしゃればご教授いただけますと幸いです。

// components/Upload.vue <template> <div> <label v-if="!value"> <input type="file" ref="file" @change="upload" > </label> <div v-if="value"> <label> <input ref="file" type="file" @change="upload" > <img :src="value" class="img-child"> </label> <button type="button" @click="deleteImage"> 削除する </button> </div> <ul v-if="fileErrorMessages.length > 0"> <li v-for="(message, index) in fileErrorMessages" :key="index"> {{ message }} </li> </ul> </div> </template> <script> export default { name: 'Upload', props: { value: { type: String, default: null } }, data(){ return { file: null, fileErrorMessages: [] } }, methods: { /* 親コンポーネントにエンコード済み画像データをバインド */ async upload( e ){ const files = e.target.files || e.dataTransfer.files const file = files[0] if ( this.checkFile( file ) ){ const picture = await this.getBase64( file ) // 親コンポーネントにエンコード済み値を渡す // inputなのは親側でv-model(内部にinputを利用)しているから this.$emit( 'input', picture ) } }, // 削除 deleteImage(){ this.$emit( 'input', null ) this.$refs.file = null }, /* 画像データチェック */ checkFile( file ){ let result = true this.fileErrorMessages = [] const SIZE_LIMIT = 5000000 // キャンセルしたら処理中断 if ( !file ){ result = false } // jpeg か png 関連ファイル以外は受け付けない if ( file.type !== 'image/jpeg' && file.type !== 'image/png' ){ this.fileErrorMessages.push( 'アップロードできるのは jpeg画像ファイル か png画像ファイルのみです。' ) result = false } // 上限サイズより大きければ受け付けない if ( file.size > SIZE_LIMIT ){ this.fileErrorMessages.push( 'アップロードできるファイルサイズは5MBまでです。' ) result = false } return result }, /* base64エンコード(ただしreadAsDataURL()利用) */ getBase64( file ){ return new Promise( ( ( resolve, reject ) => { // FileReader のインスタンスメソッドを利用してエンコード const reader = new FileReader() // FileReader.readAsDataURLで得られるのはData URIであって純粋なbase64文字列じゃないぞ reader.readAsDataURL( file ) reader.onload = () => resolve( reader.result ) reader.onerror = error => reject( error ) } ) ) }, } } </script> <style scoped> .img-child { width : 300px; } </style>
// pages/upload.vue <template> <div> <input type="text" v-model="title"> <upload v-model="picture"/> <img :src="picture" class="img"> <div v-if="picture"> <button @click="upload">アップロード</button> </div> </div> </template> <script> import Upload from "~/components/Upload"; export default { components: { Upload }, data(){ return { title: "", picture: null, uploadedPicture: null, } }, methods: { async upload(){ const dataURI = this.picture const base64EncodedFile = dataURI.replace( /data:.*/.*;base64,/, '' ) // // 予定ではここでデコードされた画像データが出力される console.log( atob( base64EncodedFile ) ) }, } } </script>
# 元画像データ File {name: "logo.png", lastModified: 1611321882584, lastModifiedDate: Fri Jan 22 2021 22:24:42 GMT+0900 (日本標準時), webkitRelativePath: "", size: 11088, …} lastModified: 1611321882584 lastModifiedDate: Fri Jan 22 2021 22:24:42 GMT+0900 (日本標準時) {} name: "logo.png" size: 11088 type: "image/png" webkitRelativePath: "" __proto__: File # base64(Data URL)のコード data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANkAAADOCAYAAACzbadVAAAACXBIWXMAACE3AAAhNwEzWJ96AAAgAElEQVR4nO2dCZQU1dXH7ww7w7BD+xERkIRoWGZQ84kgiraKxoXFz4AQBU1UiEYBxS0qgwGXSHA0UQgaZTQu0SiLCwo0izigCeoMiws6wIgLjbIMzTD7zHf+Na+anu6qrvdqr+76nTMHpqe6urqq/nXvu+++ezMaGhrIJ3UIBrKnEdFoIioiokPsZ10oHCnyL7Mz+CJLQYKB7MVENCnum5UREV7PD4Uju9P9HNmJL7IURUVoMrND4Uheup8ju/BFlsIEA9lLiWiUyjdcD7cyFI4cSvfzZDWZqf310p5pzE1U4mzmPvpYjC+yFIaNvZYm+YajWKDEx0J8kaU+6zS+YV4wkN0x3U+SlfgiS320xlwdiGhyup8kK/FFlvqM4PiGo9P9JFmJL7LUh0dAZ6f7SbISX2QpTDCQjbmw # デコードした画像(?)データ ‰PNG  IHDRÙγm§U pHYs!7!73XŸz IDATxœí ”ÕÕÇï ;ðCû„hXfPó‰ Š¶ŠÆ…ÅπMTˆFÅ-*ƒ—Hp4Qe4.Ñ(‹ 4‹8  ê ‹ :Àˆ ² Í0ûÌwþ5¯šžîª®÷j¯îú3¦§ºººªþuï»ï¾{3È'u²§Ñh"*"¢Cìg]()ò/³3ø"KA‚ìÅD4)^Ï…#»Óýى/²EEh2³CáH^ºŸ#»ðE–ÂÙK‰h”Ê7\·2ŽJ÷ód5™©ýõҞiÌMTâlæ>úXŒ/²†½–&ù†£X ÄÇB|‘¥>ë4¾a^0Ý1ÝO’•ø"K}´Æ\ˆhrºŸ$+ñE–úŒàø†£Óý$Y‰/²Ô‡G@g§ûI²_d)L0¹°^é~œÆYŠ dcœ5KôÛÙ½1‘ dó¸™>ø"KA˜ÀžÕóÍXØ[ dç§û¹4_d)sE?a-ç6Þ dû‰ÅñE–"07oQc.-Ç·hÆðEæq0‘̬×.QÂø¬Ü¸ßaÑz§ÝÉ5‰æ)ñ-Ò–¥1ýt0pJCáH4‡‘ Vi˜ ð-š|‘y Å%#å.ÆìWÍÝôE¦_d!ÈÎe"P[#¦‡:¶öl´I¢õ‰Ã™‹aã Ñ,·0ǂ#d²h}ðEæ2˜Û6šý¨-¸tq§N|‘¹€‹5ÂeŠEkɌ ¾È‚¥-ɲÂ4›d‹?}’à‹Ì&XàbD̏—‚ ~…+ýø"³6®ŠU®‡#wH¹ò+[À™IÙ£cDå÷—i¾3†_N' VE.ˆŠ

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/03/03 20:25

base64 を元に戻すより、元のファイルを送信すればいい気がしますが、一度 readAsDataUrl したらもう使えなくなるんでしたっけ?
matsuo_basho

2021/03/06 15:12

そうですね、、少なくとも 標準関数としてreadAsDataURL()でbase64にエンコードするのは用意されているのですが、デコードするのは自前で対応するしかないようです。。!
ikadzuchi

2021/03/07 16:40

どのような出力が出ることを期待しているのでしょう。画像データは文字列ではありません。
matsuo_basho

2021/03/08 02:29

@ikadzuhci ご回答ありがとうございます。 元データ(Fileオブジェクト)に戻ることを期待しているのですが、不可能なのでしょうか?
guest

回答3

0

ちょっとこの環境について詳しくないのではっきりしたことは言えないのですが、
たぶん「ファイル」と「ファイルの中身のデータ」を混同しているのだと思います。
ファイルシステム上のパスや更新日時等のメタデータを持つ「ファイル」と、ファイルの中身である純粋な「バイト列」は別のものです。

投稿2021/03/13 07:43

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matsuo_basho

2021/03/15 02:18

ご回答ありがとうございます! 確かにそのあたりの知識がないので、「ファイル」と「ファイルの中身のデータ」の混同というのはあります! 何かヒントになりそうなので、調べてみたいと思います! ありがとうございます!
guest

0

atob() ではどうでしょうか。

WindowOrWorkerGlobalScope.atob() - Web API | MDN

サンプル

js

1async function upload(e) { 2 const files = e.target.files || e.dataTransfer.files 3 const file = files[0] 4 const picture = await this.getBase64(file) 5 const binary = window.atob(picture.split(',')[1]) // バイナリ ←必要なのはこれ? 6 const arr = new TextEncoder().encode(binary) // typedArray 7 const blb = new Blob([arr.buffer], { type: 'image/png' }) // blob ←必要なのはこれ? 8 const picture2 = await this.getBase64(blb) // dataURL に戻すと 9 console.log(picture === picture2) // 一致する 10}

投稿2021/03/15 03:25

編集2021/03/15 04:21
Lhankor_Mhy

総合スコア36928

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2021/03/15 03:59

間違えているようでした。修正します。
Lhankor_Mhy

2021/03/18 03:06

ご解決されませんか? ご不明の点がありましたら、コメントでお知らせくださいね。
guest

0

戻せないこともないですが、input type=fileで受け取ってるんですから
そのデータをサブミットするだけでは?

投稿2021/03/04 00:12

yambejp

総合スコア116661

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matsuo_basho

2021/03/06 15:20

そうですね、それはそうなのですが、できれば他の理由もありbase64から元に戻したいと思っています。。 可能であればデコードする方法をご教授いただけますと幸いです。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問