2017-11-05 4 views
17

<input type="file">要素の.filesプロパティをに設定することは、例えば異なる<input type="file">要素.filesプロパティまたはDataTransfer.filesプロパティから設定できます。 Make .files settable #2866,What happens between uploading a file to an HTML form and submitting it?を参照してください。FileListオブジェクトにFileオブジェクトとlengthプロパティを設定するには、ファイルもFormDataオブジェクトに反映されますか?

FileListオブジェクトは、我々は反復可能であるFileオブジェクトしかし.files.lengthが依然として0に設定さを設定するために使用できるSymbol.iterator性を有し、通過<form>.filesが得られる上記のアプローチを用いて設定されている<input type="file">セットを有しますFile.sizeのオブジェクトは0に設定されています。 FileListFileを設定すると、ファイルがFormData()オブジェクトに設定されている設定ファイルの数にFileList.lengthを設定する方法

const input = document.createElement("input"); 
 

 
const form = document.createElement("form"); 
 

 
const [...data] = [ 
 
    new File(["a"], "a.txt") 
 
, new File(["b"], "b.txt") 
 
]; 
 

 
input.type = "file"; 
 

 
input.name = "files"; 
 

 
input.multiple = true; 
 
// set `File` objects at `FileList` 
 
input.files[Symbol.iterator] = function*() { 
 
    for (const file of data) { 
 
    yield file 
 
    }; 
 
}; 
 

 
form.appendChild(input); 
 

 
const fd = new FormData(form); 
 

 
for (const file of input.files) { 
 
    console.log(file); // `File` objects set at `data` 
 
} 
 

 
for (const [key, prop] of fd) { 
 
    // `"files"`, single `File` object having `lastModified` property 
 
    // set to a time greater than last `File` object within `data` 
 
    // at Chromium 61, only `"files"` at Firefox 57 
 
    console.log(key, prop); 
 
} 
 

 
console.log(input.files.length); // 0

+0

はそれだけで、前を編集するほうがよいのではないでしょうhttps://developer.mozilla.org/en-US/Firefox/Releases/57#DOM –

答えて

11

編集:their gistの一つで、それを行うための方法は、実際に存在し、OPによってを証明したよう

...

DataTransfer constructor(現在のBlinkによってのみサポートされています)、変更可能なFileList を作成する必要があります(現在、chromeは常に新しいFileListを返しますが、実際はm atter for us)、DataTransferItemListからアクセス可能です。

私が間違っていないのであれば、これは現在のところ賢明な方法ではありますが、同じDataTransferItemListにアクセスしてモードに設定できるClipboardEvent constructorの実装にもバグがあるようですを読み書きします。 私はスペックの解釈がわかりませんが、通常はアクセスできないはずです。

だから方法は、ファイルリスト上の任意のファイルを設定することが分かっguest271314は以下の通りである:

const dT = new ClipboardEvent('').clipboardData || // Firefox bug? 
 
    new DataTransfer();        // specs compliant 
 
dT.items.add(new File(['foo'], 'programmatically_created.txt')); 
 
inp.files = dT.files;
<input type="file" id="inp">

この発見は、デフォルトではファイルリストが変更可能なオブジェクトにするために、このnew Proposalにつながりましたもはやそれをしない点はないからです。


前(時代遅れの)答え

あなたがすることはできません。 FileListオブジェクトはスクリプト*で変更することはできません。

入力のFileListを他のFileListに交換することはできますが、変更することはできません*。
(* input.value = nullで空白を除いて)。

そして、FileListをゼロから作成することも、DataTransferオブジェクトだけを作成することもできません。また、input[type=file]はそのようなオブジェクトを作成します。

var off = inp.cloneNode(); // an offscreen input 
 

 
inp.onchange = e => { 
 
    console.log('is same before', inp.files === off.files); 
 
    off.files = inp.files; // now 'off' does have the same FileList as 'inp' 
 
    console.log('is same after', inp.files === off.files); 
 
    console.log('offscreen input FileList', off.files); 
 
    console.log('resetting the offscreen input'); 
 
    off.value = null; 
 
    console.log('offscreen input FileList', off.files);   
 
    console.log('inscreen input FileList', inp.files); 
 
}
<input type="file" id="inp">

ああそして、私はほとんどいるFormData部分を忘れてしまった、私ドンということ:他の入力のいずれかにinput[type=file]ファイルリストを設定する場合でも、新たなファイルリストが作成されていないことを示すために

:「Tは本当に私はOKそれを得たのであれば、あなたが必要とするすべては、単にFormData.append()ある...真実を言うこと

を理解しました

var fd = new FormData(); 
 

 
fd.append("files[]", new Blob(['a']), 'a.txt'); 
 
fd.append("files[]", new Blob(['b']), 'b.txt'); 
 

 
for(let pair of fd.entries()) { 
 
    console.log(pair[0], pair[1]); 
 
}

+0

を参照してくださいFF57で修正されています答え(これはまだ編集履歴で参照することができます)、答えがより簡潔になるように? –

+0

@SamuelLiew新しい部分はまだ*主にハック*です。新しい仕様(今日のBlinkで実装されている)はこれを可能にしますが、実際には設計上のものではなく、もっと偶然です。 FFのフォールバックは実装上のマイナーなバグの悪用です。興味深いハックですが、実際のAPIにつながるハックですが(https://github.com/whatwg/html/issues/3269)、当分の間、この回答の第2部分はさらに、FileListコンストラクタを使用しても有効です。FileListを変更することはできず、新しいものだけを作成することができます。 – Kaiido

関連する問題