2017-11-05 88 views
17

örneğin, farklı bir <input type="file"> elemanı .files özellik veya DataTransfer.files özelliği bir FileList için <input type="file"> elemanının .files özelliğini ayarlamak mümkündür. Bakınız Make .files settable #2866, What happens between uploading a file to an HTML form and submitting it?.Dosyaların FormData nesnesine de yansıtıldığı FileList nesnesinde File nesneleri ve length özelliği nasıl ayarlanır?

FileList DiziNesnesi iterable bir File nesne, ancak .files.length hala 0 ayarlanır ayarlamak için kullanabilir bir Symbol.iterator özelliğine sahiptir ve geçen bir <form>.files bir verir yukarıdaki yaklaşım kullanılarak ayarlanır <input type="file"> grubu olan .size olan File nesnesi 0 olarak ayarlanmıştır.

Nasıl FileList de File ayarlamak ve dosyalar FormData() nesneye ayarlanır set dosya sayısı için FileList arasında .length ayarlamak için?

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

sadece önceki kesmen iyi olmaz https://developer.mozilla.org/en-US/Firefox/Releases/57#DOM –

cevap

11

Düzenleme: their gist birinde, bunu yapmanın bir yolu aslında yoktur, OP tarafından kanıtlanmış gibi

...

DataTransfer constructor (şu anda sadece Blink tarafından desteklenen), bir değişken FileList (chrome şu anda her zaman yeni bir FileList döndürmelidir, ancak gerçekten DataTransferItemList üzerinden erişilebilir için atter.

Yanılmıyorsam, şu anda bunu yapmanın tek özellikli yolu budur, ancak Firefox'un aynı DataTransferItemList öğesinin erişilebilir ve modda ayarlandığı ClipboardEvent constructor uygulamasında da bir hata var gibi görünüyor. oku/yaz. Teknik özelliklerin yorumlanmasından emin değilim, ancak normal olarak erişilememesi gerektiğine inanıyorum.

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">

Bu keşif FileList yapmak için bu new Proposal yol açmıştır varsayılan olarak kesilebilir nesneleri:

Yani yolu bir FileList üzerinde keyfi dosyaları ayarlamak bulunmuştur guest271314 aşağıdaki gibidir Çünkü artık yapmayacak bir nokta yok.


Önceki (eski) cevap

Yapamazsın. FileList nesneleri komut dosyaları ile değiştirilemez *.

Bir girdinin FileList'ını yalnızca başka bir FileList'e dönüştürebilirsiniz, ancak değiştiremezsiniz *.
(* input.value = null ile boşaltma hariç).

Sen de sıfırdan FileList oluşturamaz, sadece DataTransfer ya oluşturulamaz nesneleri ve input[type=file] tür nesneleri yaratacaktır.

bir diğer girişin birine bir input[type=file] FileList ayarı bile hiçbir yeni FileList oluşturulduğunu göstermek için:

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">

Ah Ve neredeyse, FormData kısmını unuttum ı don Ben Tamam var 'yi gerçekten ... Yani

gerçeği söylemek anlaşılan, tek ihtiyacınız sadece FormData.append() geçerli:

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

bkz FF57 sabit olmuştur Cevap (ki hala düzenleme tarihi ile referans alınabilir), böylece cevap daha kısa olabilir mi? –

+0

@SamuelYeni yeni parça hala * esas olarak bir kesmek *. Yeni özellikler (bugün sadece Blink'te uygulandığı için) buna izin veriyor, ama tasarım gereği değil, daha çok tesadüf. FF geri dönüşü, uygulamalarında küçük bir hatanın kötüye kullanılmasıdır. Bu yüzden, muhtemelen [gerçek bir API'ye yol açacak] ilginç bir hack olsa da (https://github.com/whatwg/html/issues/3269), şimdilik bu cevabın ikinci kısmına inanıyorum. Dahası, yine de, bir FileList yapıcısıyla bile geçerli olmaya devam eder: Bir FileList'i değiştiremezsiniz, sadece yenilerini yaratamazsınız. – Kaiido