2017-11-05 14 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 개체 및 길이 속성을 설정하는 방법 파일도 FormData 개체에도 반영됩니까?

FileList 목적은 우리가 반복 가능한있는 File 오브젝트 그러나 .files.length 여전히 0로 설정을 설정하는 데 사용할 수있는 Symbol.iterator 속성을 가지며, 통과하는 <form>.files가 수득 상기 방법을 사용하여 설정 <input type="file"> 세트를 갖는 .size을 갖는 File 오브젝트는 0으로 설정됩니다.

어떻게 FileList에서 File을 설정하고 파일이 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 중 하나에 그것을 할 수있는 방법이 실제로 존재, 영업 이익에 의해 입증으로

...

DataTransfer constructor (현재를 Blink에서만 지원), 변경 가능한 FileList 을 생성해야합니다 (현재 크롬은 항상 새 FileList를 반환하지만 실제로는 m atter for us), DataTransferItemList를 통해 액세스 할 수 있습니다.

내가 실수하지 않았다면, 현재이 방법을 쓰는 것이 유일한 방법이지만 Firefox는 ClipboardEvent constructor 구현에 버그가있는 것 같습니다. 동일한 DataTransferItemList에 액세스하여 모드로 설정할 수 있습니다 읽기/쓰기. 스펙에 대한 내 해석이 확실하지 않지만 정상적으로 액세스 할 수 없어야한다고 생각합니다.

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로 이어질했다 기본적으로 변경 가능한 객체 :

그래서 방법은 파일 목록에서 임의의 파일을 설정하는 것으로 guest271314은 다음과 같다 더 이상 할 일이 없기 때문에.


이전 (오래된) 대답

당신은 할 수 없습니다. FileList 객체는 스크립트 *로 수정할 수 없습니다.

입력의 FileList를 다른 FileList로만 교환 할 수 있지만 수정할 수는 없습니다 *.
(* input.value = null으로 비움 제외).

처음부터 FileList를 만들 수없고 DataTransfer 개체 만 만들 수없고 input[type=file] 개체 만 만들 수 있습니다.

하는 것은 다른 입력의 하나에 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 부분을 잊었 I 돈 진실을 말하기 위해 정말로 이해하지 못했습니다 ...

그래도 괜찮 으면 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 fallback은 구현시 사소한 버그를 남용하는 것입니다. 당분간은 실제 API (https://github.com/whatwg/html/issues/3269)로 연결되는 흥미로운 해킹이지만,이 답변의 두 번째 부분은 여전히 FileList 생성자를 사용하더라도 여전히 유효합니다. FileList를 수정할 수없고 새 파일 만 만들 수 있습니다. – Kaiido