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

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

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

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

Q&A

2回答

3214閲覧

【JavaScript】FileReaderを用いた複数の添付ファイルのパラメータ取得方法について

floor

総合スコア12

JavaScript

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

0グッド

0クリップ

投稿2020/11/02 03:40

前提・実現したいこと

JavaScript の FileReader を用いて複数の添付ファイルを読み込んでいます。
最終的にはフロント側で読み込んだ添付ファイルのパラメータをバックエンド側に渡したいと思っております。

発生している問題

バックエンド側でログを出力すると、fileName の値は取得できましたが、fileList は NULL となりました。
(バックエンド側は特殊な言語を使用している為、回答を得にくい為こちらの処理については割愛させて頂きます)
そこで、フロント側の fileList に情報が格納されていないのではと推測しましたが、
バックエンド側に値を渡す前に、コンソールにログを出力したところ、値は格納されているように見受けられます。

試しに、console.log(param.fileList[0].name);といったように、
実行結果で出力しているファイル名の「test1.pdf」が取得できるかログを出力してみましたが、
「undefined」となり、fileList に格納されている値を抽出できない為、NULL となっているのではと考えました。
fileList に格納されている各パラメーター(name, file)の取得方法について、知恵をお貸し頂ければ幸いです。

該当のソースコード

JavaScript

1$("#uploadButton").click(function(){ 2 var uploadFile = document.getElementById('uploadFile'); 3 var param = new Object(); 4 param.fileName = ''; 5 param.fileList = []; 6 var returnParam = new Object(); 7 8 for(let i = 0; i < uploadFile.files.length; i++) { 9 var file = uploadFile.files[i]; 10 if(i == 0) { 11 param.fileName = file.webkitRelativePath; 12 } else { 13 returnParam = readFile(file); 14 param.fileList.push(returnParam); 15 } 16 } 17 console.log(param); 18 uploadAttachments(param); 19}); 20 21function readFile(file) { 22 var inputFile = new Object(); 23 var reader = new FileReader(); 24 reader.readAsDataURL(file); 25 reader.onloadend = function() { 26 var dataURL = reader.result; 27 inputFile['name'] = file.name; 28 inputFile['file'] = dataURL.match(/,(.*)$/)[1]; 29 }; 30 return inputFile; 31}

コンソール実行結果

console.log(param); を実行した結果

▼{fileName: "2020-11-01 00.00.00", fileList: Array(3)} fileName: "2020-11-01 00.00.00" ▼fileList: Array(3) ▶︎0: {name: "test1.pdf", file: "AAAA......"} ▶︎1: {name: "test2.pdf", file: "AAAA......"} ▶︎2: {name: "test3.pdf", file: "AAAA......"}

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

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

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

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

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

yambejp

2020/11/02 03:49

ajax的な処理が不要なら普通にサブミットするだけでは?
floor

2020/11/02 04:00

ご回答頂きまして有難うございます。 回答を得難いと思い処理は割愛させて頂きましたが、Attachments メソッドでは、「JavaScript Remoting」を使用してコントローラへのAJAX要求を行い、パラメータ(param)を渡しております。 その為、パラメータ(param)に値が格納されているかをコンソールで確認したいと思っておりました。
yambejp

2020/11/02 05:18

FileReaderは重要ですか? ふつうajaxでファイル転送するときはFormDataで指定すれば済みますが・・・
floor

2020/11/02 05:34

ご確認頂き有難うございます。 複数ファイルでないサンプルソースが FileReader を用いて実装していた為、FileReader に固執しておりましたが、FormData で実装できないか再度試してみたいと思います。助言頂きまして有難うございました。
guest

回答2

0

FormDataで送るならこんな感じで

投稿2020/11/02 05:46

yambejp

総合スコア116724

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

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

yambejp

2020/11/02 05:46

<form method="post" action="送り先" enctype="multipart/form-data" > <input type="file" name="f[]" multiple> <input type="submit" value="fetch" id="btn"> </form> <script> window.addEventListener('DOMContentLoaded', ()=>{ document.querySelector('#btn').addEventListener('click',e=>{ e.preventDefault(); const f=e.target.form; const method=f.method; const body=new FormData(f); fetch(f.action,{body,method}).then(res=>res.text()).then(console.log); }); }); </script>
floor

2020/11/02 05:52

ご回答頂きまして有難うございます。 こちらを参考に FormData を用いた方法でも試してみたいと思います。
guest

0

fileList は NULL となりました。(中略)値は格納されているように見受けられます。

FileReader は 非同期処理ですので、開発者コンソールの状況は 時間差で格納される ことを示しています。

次のいずれかで対策します。

  1. コールバック関数をネストする(コールバック地獄
  2. Promiseによる同期的な処理を考える(フロー制御

イベント処理など非同期処理の多い JavaScript ではコールバック関数の取扱が必須知識になります


知恵をお貸し頂ければ幸いです

「コールバック地獄」だとこんな感じ。

javascript

1$("#uploadButton").click(function(){ 2 let 3 uploadFile = document.getElementById('uploadFile'), // input[type="file"] ? 4 param = { 5 fileName : '', // 相対Path?(Chrome系) 6 fileList : [] // 変換後のfileパラメータ一覧 7 }, // カンマ忘れ(訂正 8 isAllCmpl = () => param.fileList.length === uploadFile.files.length 9 ; 10 11 for ( let i = 0; i < uploadFile.files.length; i++ ) { 12 13 let file = uploadFile.files[i]; 14 if ( i == 0 ) { 15 param.fileName = file.webkitRelativePath; 16 } 17 // uploadFile.files[0] の時も file を読む 18 19 // コールバック関数は FileReaderの処理完了順に実行される 20 readFile( file, function( info ) { 21 param.fileList.push(info); 22 if ( isAllCmpl() ) { 23 // 全て完了した時の処理(ブロックを見てもネストが深くなる) 24 } 25 }); 26 } 27}); 28 29function readFile(file, callback) { 30 31 Object.assign(new FileReader(), { 32 onloadend( evt ) { 33 let dataURL = evt.target.result; 34 callack({ name: file.name, file: dataURL.match(/,(.*)$/)[1] }); 35 } 36 }).readAsDataURL(file); 37}

投稿2020/11/02 05:37

編集2020/11/02 05:47
AkitoshiManabe

総合スコア5434

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

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

floor

2020/11/02 05:51

ご回答頂きまして有難うございます。 大変良く分かりました、フロント側の知識が浅くお恥ずかしい限りですが、こちらを参考にまず試してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問