मैंने ऐसा कोई उदाहरण नहीं देखा है जो ऐसा करता हो। क्या एपीआई युक्ति में इसकी अनुमति नहीं है?
मैं फ़ोटो के संपूर्ण फ़ोल्डर ट्री को अपलोड करने के लिए एक आसान ड्रैग-ड्रॉप समाधान खोज रहा हूं।
मैंने ऐसा कोई उदाहरण नहीं देखा है जो ऐसा करता हो। क्या एपीआई युक्ति में इसकी अनुमति नहीं है?
मैं फ़ोटो के संपूर्ण फ़ोल्डर ट्री को अपलोड करने के लिए एक आसान ड्रैग-ड्रॉप समाधान खोज रहा हूं।
जवाबों:
यह अब संभव है, Chrome> = 21 के लिए धन्यवाद।
function traverseFileTree(item, path) {
path = path || "";
if (item.isFile) {
// Get file
item.file(function(file) {
console.log("File:", path + file.name);
});
} else if (item.isDirectory) {
// Get folder contents
var dirReader = item.createReader();
dirReader.readEntries(function(entries) {
for (var i=0; i<entries.length; i++) {
traverseFileTree(entries[i], path + item.name + "/");
}
});
}
}
dropArea.addEventListener("drop", function(event) {
event.preventDefault();
var items = event.dataTransfer.items;
for (var i=0; i<items.length; i++) {
// webkitGetAsEntry is where the magic happens
var item = items[i].webkitGetAsEntry();
if (item) {
traverseFileTree(item);
}
}
}, false);
अधिक जानकारी: https://protonet.info/blog/html5-experiment-drag-drop-of-folders/
readEntries
निर्देशिका में सभी एंटायर वापस नहीं आएंगे। आपके द्वारा दिए गए बग लिंक के आधार पर, मैंने एक पूर्ण उत्तर लिखा है: stackoverflow.com/a/53058574/885922
दुर्भाग्यवश मौजूदा उत्तरों में से कोई भी पूरी तरह से सही readEntries
नहीं है क्योंकि किसी दिए गए निर्देशिका के लिए सभी (फ़ाइल या निर्देशिका) प्रविष्टियों को जरूरी नहीं लौटाया जाएगा । यह एपीआई विनिर्देश का हिस्सा है (नीचे प्रलेखन अनुभाग देखें)।
वास्तव में सभी फाइलें प्राप्त करने के लिए, हमें readEntries
एक खाली सरणी वापस आने तक बार-बार कॉल करने की आवश्यकता होगी (प्रत्येक निर्देशिका जो हम मुठभेड़ करते हैं)। यदि हम नहीं करते हैं, तो हम एक निर्देशिका में कुछ फ़ाइलों / उप-निर्देशिकाओं को याद करेंगे जैसे कि क्रोम में, readEntries
केवल एक समय में अधिकतम 100 प्रविष्टियों में वापस आ जाएगी।
का उपयोग करते हुए वादे ( await
/ async
) और अधिक स्पष्ट रूप से सही उपयोग प्रदर्शित करने के लिए readEntries
(क्योंकि यह अतुल्यकालिक है), और चौड़ाई-पहले खोज (BFS) निर्देशिका संरचना पार करने के लिए:
// Drop handler function to get all files
async function getAllFileEntries(dataTransferItemList) {
let fileEntries = [];
// Use BFS to traverse entire directory/file structure
let queue = [];
// Unfortunately dataTransferItemList is not iterable i.e. no forEach
for (let i = 0; i < dataTransferItemList.length; i++) {
queue.push(dataTransferItemList[i].webkitGetAsEntry());
}
while (queue.length > 0) {
let entry = queue.shift();
if (entry.isFile) {
fileEntries.push(entry);
} else if (entry.isDirectory) {
queue.push(...await readAllDirectoryEntries(entry.createReader()));
}
}
return fileEntries;
}
// Get all the entries (files or sub-directories) in a directory
// by calling readEntries until it returns empty array
async function readAllDirectoryEntries(directoryReader) {
let entries = [];
let readEntries = await readEntriesPromise(directoryReader);
while (readEntries.length > 0) {
entries.push(...readEntries);
readEntries = await readEntriesPromise(directoryReader);
}
return entries;
}
// Wrap readEntries in a promise to make working with readEntries easier
// readEntries will return only some of the entries in a directory
// e.g. Chrome returns at most 100 entries at a time
async function readEntriesPromise(directoryReader) {
try {
return await new Promise((resolve, reject) => {
directoryReader.readEntries(resolve, reject);
});
} catch (err) {
console.log(err);
}
}
कोडपेन पर पूरा कार्य करने वाला उदाहरण: https://codepen.io/anon/pen/gBJrOP
एफडब्ल्यूआईडब्ल्यू मैंने केवल इसे उठाया क्योंकि मुझे स्वीकार किए गए उत्तर का उपयोग करते समय 40,000 फाइलों (कई निर्देशिकाओं में अच्छी तरह से 100 फाइलों / उप-निर्देशिकाओं से युक्त) में अपेक्षित सभी फाइलें वापस नहीं मिल रही थीं।
प्रलेखन:
इस व्यवहार में प्रलेखित है FileSystemDirectoryReader । जोर के साथ जोड़ा:
readEntries ()
एक सरणी देता है जिसमें कुछ संख्या होती है निर्देशिका की प्रविष्टियों। सरणी में प्रत्येक आइटम FileSystemEntry पर आधारित एक वस्तु है - आमतौर पर या तो FileSystemFileEntry या FileSystemDirectoryEntry।
लेकिन निष्पक्ष होने के लिए, एमडीएन प्रलेखन अन्य वर्गों में यह स्पष्ट कर सकता है। ReadEntries () प्रलेखन बस नोट:
readEntries () विधि निर्देशिका निर्देशिका को पढ़ा जा रहा है और उन्हें उपलब्ध कॉलबैक फ़ंक्शन में एक सरणी में वितरित करता है
और केवल उल्लेख / संकेत है कि कई कॉल की जरूरत है के विवरण में है सफल कॉलबैक पैरामीटर :
यदि कोई फ़ाइल नहीं बची है, या आपने पहले से ही इस FileSystemDirectoryReader पर readEntries () कहा है, तो सरणी खाली है।
यकीनन एपीआई अधिक सहज हो सकता है, लेकिन प्रलेखन नोटों के रूप में: यह एक गैर-मानक / प्रायोगिक विशेषता है, एक मानक ट्रैक पर नहीं, और सभी ब्राउज़रों के लिए काम करने की उम्मीद नहीं की जा सकती है।
सम्बंधित:
readEntries
एक निर्देशिका के लिए अधिकतम 100 प्रविष्टियों (Chrome 64 के रूप में सत्यापित) पर वापस आ जाएगा।readEntries
इस उत्तर में काफी अच्छी तरह से सही उपयोग बताता है (यद्यपि कोड के बिना)।readEntries
बिना एक अतुल्यकालिक तरीके से कहता है। वह यह भी नोट करता है कि फ़ायरफ़ॉक्स एक निर्देशिका में (क्रोम के विपरीत) सभी प्रविष्टियाँ लौटाता है लेकिन हम इस दिए गए विनिर्देश पर भरोसा नहीं कर सकते हैं।FileSystemFileEntry
को परिवर्तित करने की आवश्यकता है । यदि आपको भी पूर्ण मार्ग की आवश्यकता है, तो आपको इसे ( केवल नाम होगा) से लेना चाहिए । File
file(successCb, failureCb)
fileEntry.fullPath
file.webkitRelativePath
यह फ़ंक्शन आपको सभी गिराई गई फ़ाइलों की सरणी के लिए एक वादा देगा, जैसे <input type="file"/>.files
:
function getFilesWebkitDataTransferItems(dataTransferItems) {
function traverseFileTreePromise(item, path='') {
return new Promise( resolve => {
if (item.isFile) {
item.file(file => {
file.filepath = path + file.name //save full path
files.push(file)
resolve(file)
})
} else if (item.isDirectory) {
let dirReader = item.createReader()
dirReader.readEntries(entries => {
let entriesPromises = []
for (let entr of entries)
entriesPromises.push(traverseFileTreePromise(entr, path + item.name + "/"))
resolve(Promise.all(entriesPromises))
})
}
})
}
let files = []
return new Promise((resolve, reject) => {
let entriesPromises = []
for (let it of dataTransferItems)
entriesPromises.push(traverseFileTreePromise(it.webkitGetAsEntry()))
Promise.all(entriesPromises)
.then(entries => {
//console.log(entries)
resolve(files)
})
})
}
dropArea.addEventListener("drop", function(event) {
event.preventDefault();
var items = event.dataTransfer.items;
getFilesFromWebkitDataTransferItems(items)
.then(files => {
...
})
}, false);
https://www.npmjs.com/package/datatransfer-files-promise
उपयोग का उदाहरण: https://github.com/grabantot/datatransfer-files-promise/blob/master/index.html
function getFilesWebkitDataTransferItems(dataTransfer)
होनी चाहिए function getFilesWebkitDataTransferItems(items)
, और for (entr of entries)
होनी भी चाहिए for (let entr of entries)
।
readEntries
बार-बार कॉल करने की आवश्यकता को तब तक निर्धारित करता है जब तक कि वह खाली सरणी नहीं देता।
HTML 5 मेलिंग सूची में इस संदेश में इयान हिकसन कहते हैं:
HTML5 को अब एक साथ कई फाइलें अपलोड करनी हैं। ब्राउजर उपयोगकर्ताओं को एक साथ कई फाइलें लेने की अनुमति दे सकता है, जिसमें कई निर्देशिकाएं शामिल हैं; यह कल्पना के दायरे से बाहर है।
(मूल भी देखें फीचर प्रस्ताव ।) इसलिए यह मान लेना सुरक्षित है कि वह ड्रैग-एंड-ड्रॉप का उपयोग करके फ़ोल्डर्स अपलोड करने पर भी विचार करता है। जाहिर है यह व्यक्तिगत फ़ाइलों की सेवा करने के लिए ब्राउज़र पर निर्भर है।
फ़ोल्डर अपलोड करने में कुछ अन्य कठिनाइयाँ भी होंगी, जैसा कि लार्स गुनथर द्वारा वर्णित है :
इस […] प्रस्ताव में दो जाँचें होनी चाहिए (यदि यह सब करने योग्य है):
अधिकतम आकार, किसी को कई सौ असम्पीडित कच्ची छवियों की पूर्ण निर्देशिका अपलोड करने से रोकने के लिए ...
फ़िल्टरिंग भले ही स्वीकार विशेषता छोड़ दी गई हो। मैक ओएस मेटाडेटा और विंडोज थंबनेल आदि को छोड़ दिया जाना चाहिए। सभी छिपी हुई फ़ाइलों और निर्देशिकाओं को बाहर रखा जाना चाहिए।
अब आप डायरेक्टरी को ड्रैग एंड ड्रॉप और इनपुट दोनों के साथ अपलोड कर सकते हैं।
<input type='file' webkitdirectory >
और खींचें और ड्रॉप के लिए (वेबकिट ब्राउज़र के लिए)।
फ़ोल्डर्स को ड्रैग और ड्रॉप करना।
<div id="dropzone"></div>
<script>
var dropzone = document.getElementById('dropzone');
dropzone.ondrop = function(e) {
var length = e.dataTransfer.items.length;
for (var i = 0; i < length; i++) {
var entry = e.dataTransfer.items[i].webkitGetAsEntry();
if (entry.isFile) {
... // do whatever you want
} else if (entry.isDirectory) {
... // do whatever you want
}
}
};
</script>
संसाधन:
http://updates.html5rocks.com/2012/07/Drag-and-drop-a-folder-onto-Chrome-now-available
फ़ायरफ़ॉक्स अब 15 नवंबर, 2016 को v50.0 में फ़ोल्डर अपलोड का समर्थन करता है: https://developer.mozilla.org/en-US/Firefox/Releases/50#Files_and_directories
आप फ़ायरफ़ॉक्स में फ़ोल्डरों को खींच सकते हैं और छोड़ सकते हैं या अपलोड करने के लिए ब्राउज़ कर सकते हैं और एक स्थानीय फ़ोल्डर चुन सकते हैं। यह सबफ़ोल्डर में नेस्टेड फ़ोल्डर का भी समर्थन करता है।
इसका मतलब है कि अब आप फ़ोल्डरों को अपलोड करने के लिए क्रोम, फ़ायरफ़ॉक्स, एज या ओपेरा का उपयोग कर सकते हैं। आप वर्तमान में Safari या Internet Explorer का उपयोग नहीं कर सकते हैं।
फ़ाइल और निर्देशिका प्रविष्टियों का उपयोग कैसे करें एपीआई का एक पूरा उदाहरण यहां दिया गया है :
var dropzone = document.getElementById("dropzone");
var listing = document.getElementById("listing");
function scanAndLogFiles(item, container) {
var elem = document.createElement("li");
elem.innerHTML = item.name;
container.appendChild(elem);
if (item.isDirectory) {
var directoryReader = item.createReader();
var directoryContainer = document.createElement("ul");
container.appendChild(directoryContainer);
directoryReader.readEntries(function(entries) {
entries.forEach(function(entry) {
scanAndLogFiles(entry, directoryContainer);
});
});
}
}
dropzone.addEventListener(
"dragover",
function(event) {
event.preventDefault();
},
false
);
dropzone.addEventListener(
"drop",
function(event) {
var items = event.dataTransfer.items;
event.preventDefault();
listing.innerHTML = "";
for (var i = 0; i < items.length; i++) {
var item = items[i].webkitGetAsEntry();
if (item) {
scanAndLogFiles(item, listing);
}
}
},
false
);
body {
font: 14px "Arial", sans-serif;
}
#dropzone {
text-align: center;
width: 300px;
height: 100px;
margin: 10px;
padding: 10px;
border: 4px dashed red;
border-radius: 10px;
}
#boxtitle {
display: table-cell;
vertical-align: middle;
text-align: center;
color: black;
font: bold 2em "Arial", sans-serif;
width: 300px;
height: 100px;
}
<p>Drag files and/or directories to the box below!</p>
<div id="dropzone">
<div id="boxtitle">
Drop Files Here
</div>
</div>
<h2>Directory tree:</h2>
<ul id="listing"></ul>
webkitGetAsEntry
क्रोम 13+, फ़ायरफ़ॉक्स 50+ और एज द्वारा समर्थित है।
स्रोत: https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry
क्या HTML5 फ़ोल्डर्स या फ़ोल्डर ट्री के ड्रैग-ड्रॉप अपलोड की अनुमति देता है?
केवल क्रोम इस सुविधा का समर्थन करता है। यह किसी भी कर्षण के लिए विफल रहा है और इसे हटाए जाने की संभावना है।
रेफरी: https://developer.mozilla.org/en/docs/Web/API/DirectoryReader###Ebries
readEntries
नहीं किया जा सकता है अगर कोई अन्य कॉल readEntries
अभी भी चलाया जा रहा है। DirectoryReader एपीआई डिजाइन सबसे अच्छा नहीं है
अद्यतन: 2012 के बाद से बहुत कुछ बदल गया है, इसके बजाय उत्तर देखें। मैं इस उत्तर को पुरातत्व की खातिर यहाँ छोड़ता हूँ।
HTML5 कल्पना यह नहीं कहती है कि अपलोड के लिए एक फ़ोल्डर का चयन करते समय, ब्राउज़र को सभी निहित फ़ाइलों को पुन: अपलोड करना चाहिए।
दरअसल, क्रोम / क्रोमियम में, आप एक फ़ोल्डर अपलोड कर सकते हैं, लेकिन जब आप ऐसा करते हैं, तो यह केवल एक अर्थहीन 4KB फाइल अपलोड करता है, जो निर्देशिका का प्रतिनिधित्व करता है। अल्फ़्रेस्को जैसे कुछ सर्वर-साइड एप्लिकेशन इसका पता लगा सकते हैं, और उपयोगकर्ता को चेतावनी दे सकते हैं कि फ़ोल्डर अपलोड नहीं किए जा सकते हैं:
हाल ही में मेरी दो परियोजनाओं में इसे लागू करने की आवश्यकता पर अड़ गए हैं इसलिए मैंने इसके साथ मदद करने के लिए उपयोगिता कार्यों का एक समूह बनाया।
एक एक डेटा-संरचना बनाता है जो सभी फ़ोल्डरों, फाइलों और उनके बीच के संबंधों का प्रतिनिधित्व करता है, जैसे कि structure
{
folders: [
{
name: string,
folders: Array,
files: Array
},
/* ... */
],
files: Array
}
जबकि दूसरा सिर्फ सभी फाइलों (सभी फ़ोल्डरों और सब-फ़ोल्डर्स में) का एक Array देता है।
यहां पैकेज का लिंक दिया गया है: https://www.npmjs.com/package/file-system-utils
input type=file
: stackoverflow.com/questions/9518335/…