質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.47%
canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

DOM

DOMは、Document Object Modelの略で、HTML文書やXML文書をアプリケーションから利用するためのAPIです。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

Q&A

解決済

2回答

2250閲覧

localStorageから読みだした画像ファイルを、DataTransferで作成した input type="file"にセットしたい

nakanohitobot

総合スコア48

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

DOM

DOMは、Document Object Modelの略で、HTML文書やXML文書をアプリケーションから利用するためのAPIです。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

0グッド

0クリップ

投稿2022/01/19 07:06

以下の①~④ができるようにしたいです。
①ユーザーが画像ファイル選択
②localStrageに①のファイルを保存
③ページ再読み込み時に②で保存した画像ファイルを読み出し
④new DataTransferで input type="file" 要素を新たに作成する際に、③で読み出した画像ファイルをセット
⑤submitを行う

ユーザーが画像ファイルを選択して、そのファイルを、DataTransferで新たに作成した、input type="file"要素にセットするところまでは、確認できています。(localStrage不使用)

JavaScript

1let uploadImage = document.getElementsByName("uploadImage").item(0); 2let inputTemplate = document.createElement('input'); 3inputTemplate.setAttribute("name", "uploadImage"); 4inputTemplate.type = 'file'; 5 6uploadImage.addEventListener('change', e => { 7 const {files} = e.target; 8 const dt = new DataTransfer(); 9 dt.items.add(files[0]); 10 inputTemplate.files = dt.files; 11 dt.setData("Files", files[0]); 12 let file = dt.files; 13 let form = document.getElementById("form"); 14 form.appendChild(inputTemplate); 15}, false)

問題は、localStrageが絡んできた時です。
localStrageに画像を保存するために、Canvasでbase64にエンコードしています。
読み出し時に、base64のデコードを行いましたが、このデータを、どのようにして、new DataTransferで新たに作成する input type="file" 要素にセットすればいいのか不明です。

JavaScript

1let uploadImage = document.getElementsByName("uploadImage").item(0); 2 3uploadImage.addEventListener('change', e => { 4 var reader = new FileReader(); 5 reader.onload = function() { 6 var img = new Image(); 7 img.onload = function() { 8 var canvas = document.createElement('canvas'); 9 var context = canvas.getContext('2d'); 10 canvas.width=img.width; 11 canvas.height=img.height; 12 context.drawImage(img,0,0); 13 localStorage.setItem("hoge", canvas.toDataURL("image/jpeg")); 14 }; 15 img.src=reader.result; 16 }; 17 reader.readAsDataURL(uploadImage.files[0]); 18 19 var imgres = new Image(); 20 imgres.onload = function() { 21 var canvas = document.createElement('canvas'); 22 var context = canvas.getContext('2d'); 23 canvas.width=imgres.width; 24 canvas.height=imgres.height; 25 context.drawImage(imgres,0,0); 26 } 27 let imageData = localStorage.getItem("hoge"); 28 let decodeImage = imageData.split('data:image/jpeg;base64,')[1]; 29 let result = atob(decodeImage); 30 console.log(result); 31// base64のデコードが正常に完了している。これをどのようにしてDataTransferで作成するinput type="file"にセットすればいいか不明 32}, false)

やり方が違いますが、以下のリンク先でファイルの選択状態まで復元できている方がいるので、できないことはないのだと思います。
アップロードファイルを localStorage に保存して、再アクセス時にファイルを復元する
ただ、このページ記載の方法だと、不完全なコードなのかうまく動かない状態でして、困っています。

どなたか、DataTransferで作成するinput type="file"にセットする方法を、ご存じの方がいればご教授いただきたいです。
よろしくおねがいします。

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

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

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

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

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

int32_t

2022/01/19 07:59 編集

質問文のコード、画像形式を jpeg に変換する意図がない場合は Image は不要です。 reader.onload の中は localStorage.setItem("hoge", reader.result); だけでいいです。
guest

回答2

0

ベストアンサー

atob()の結果のresult は変な文字列表現のバイナリなので、それを Uint8Array に変換して、new File()File インスタンスを作って DataTransfer にセットすればいいんじゃないでしょうか。

(本当に動くかどうかは未検証です)
追記: 参考ページに似たようなことが書いてあることに気付きました。参考ページを読んで、さらに質問文にはDataTransfer経由でFileをセットするコードを既に書いてらして、何がわからないんでしょう。

投稿2022/01/19 07:20

編集2022/01/19 08:42
int32_t

総合スコア20929

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

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

nakanohitobot

2022/01/19 10:16

ご回答ありがとうございます。 参考ページを参照に試してみたところ、DataTransferにセットすることができました。(おっしゃるとUint8Arrayに変換後、Fileインスタンスを作成しました) しかし、最初ユーザーがファイルを選択した時と、Uint8Arrayに変換後に、Fileインスタンスを作成した時では、File.sizeプロパティの値が異なってしまいます。 sizeプロパティは、インスタンス作成時にも手動で設定することは不可能なようで、困っております。
int32_t

2022/01/19 13:06

> File.sizeプロパティの値が異なってしまいます。 質問文のコードのようにcanvasに描画してjpegにエンコードしていると、もとのファイルがjpegのときでさえバイナリのサイズは異なることが多くなります。 canvasを経由しなくてもサイズが変わるようだと、どこかバグってます。
nakanohitobot

2022/01/19 13:16 編集

canvas経由をやめて、参考サイトのように、new FileReaderを使用しました。 ただ、これでもファイルサイズが異なってしまうため、どうしようかと思いましたが、 どうやら、base64のデコード結果を、直接new Fileに渡しているのが、まずかったようです。 一度new Blobに渡してから、Blob → Fileへの変換を行うと、問題ありませんでした。 ひとまずやりたいことが出来ました! ありがとうございました。
guest

0

type=fileにセットすることはできません
逆にセットする必要はなく、submitやfetchなどでサーバーに送ることはできます

投稿2022/01/19 07:12

yambejp

総合スコア114919

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

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

nakanohitobot

2022/01/19 10:18

ご回答ありがとうございます。 参考先のページが、結果的に同じことができたようで(ユーザーがファイルを選択したときの復元)試してみようとおもいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問