Skip to content

Commit 9b706e9

Browse files
authored
[Bug, EC] PEES-771: Bug fix too much recursion when uploading lots of file (#1026)
* prevent inifite recursion * Update tree.js * Change var to let in for loop for entries * Update public/js/pimcore/asset/tree.js * Refactor folder upload handling for better performance * Increase MAX_DEPTH and switch from stack to queue FIFO
1 parent d52cee2 commit 9b706e9

File tree

1 file changed

+91
-55
lines changed

1 file changed

+91
-55
lines changed

public/js/pimcore/asset/tree.js

Lines changed: 91 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -361,61 +361,97 @@
361361
});
362362
}.bind(this);
363363

364-
if(dataTransfer["items"] && dataTransfer.items[0] && dataTransfer.items[0].webkitGetAsEntry) {
365-
// chrome
366-
var traverseFileTree = function (item, path) {
367-
path = path || "";
368-
if (item.isFile) {
369-
// Get file
370-
item.file(function (file) {
371-
doFileUpload(file, path);
372-
}.bind(this));
373-
} else if (item.isDirectory) {
374-
// Get folder contents
375-
var dirReader = item.createReader();
376-
dirReader.readEntries(function (entries) {
377-
for (var i = 0; i < entries.length; i++) {
378-
traverseFileTree(entries[i], path + item.name + "/");
379-
}
380-
});
381-
}
382-
}.bind(this);
383-
384-
for (var i = 0; i < dataTransfer.items.length; i++) {
385-
// webkitGetAsEntry is where the magic happens
386-
var item = dataTransfer.items[i].webkitGetAsEntry();
387-
if (item) {
388-
traverseFileTree(item);
389-
}
390-
}
391-
} else if(dataTransfer["files"]) {
392-
// default filelist upload
393-
for (var i=0; i<dataTransfer["files"].length; i++) {
394-
file = dataTransfer["files"][i];
395-
396-
if (window.FileList && file.name && file.size) { // check for size (folder has size=0)
397-
doFileUpload(file);
398-
} else if (!empty(file.type) && file.size < 1) { //throw error for 0 byte file
399-
Ext.MessageBox.alert(t('error'), t('error_empty_file_upload'));
400-
win.close();
401-
}
402-
}
403-
404-
// if no files are uploaded (doesn't match criteria, ...) close the progress win immediately
405-
if(!this.activeUploads) {
406-
win.close();
407-
}
408-
}
409-
410-
// check in 5 sec. if there're active uploads
411-
// if not, close the progressbar
412-
// this is necessary since the folder upload is async, so we don't know if the progress is
413-
// necessary or not, not really perfect solution, but works as it should
414-
window.setTimeout(function () {
415-
if(!this.activeUploads) {
416-
win.close();
417-
}
418-
}.bind(this), 5000);
364+
if (dataTransfer["items"] && dataTransfer.items[0] && dataTransfer.items[0].webkitGetAsEntry) {
365+
// Chrome-specific folder support
366+
const MAX_DEPTH = 20;
367+
const queue = [];
368+
369+
for (let i = 0; i < dataTransfer.items.length; i++) {
370+
const item = dataTransfer.items[i].webkitGetAsEntry();
371+
if (item) {
372+
queue.push({ item, path: "", depth: 0 });
373+
}
374+
}
375+
376+
const processNext = () => {
377+
if (queue.length === 0) return;
378+
379+
const { item, path, depth } = queue.shift();
380+
381+
if (depth > MAX_DEPTH) {
382+
setTimeout(processNext, 0);
383+
return;
384+
}
385+
386+
if (item.isFile) {
387+
item.file(
388+
(file) => {
389+
doFileUpload(file, path);
390+
setTimeout(processNext, 0);
391+
},
392+
() => {
393+
setTimeout(processNext, 0);
394+
}
395+
);
396+
} else if (item.isDirectory) {
397+
const dirReader = item.createReader();
398+
399+
const readEntries = () => {
400+
dirReader.readEntries(
401+
(entries) => {
402+
if (entries.length === 0) {
403+
setTimeout(processNext, 0);
404+
return;
405+
}
406+
407+
for (let i = 0; i < entries.length; i++) {
408+
queue.push({
409+
item: entries[i],
410+
path: path + item.name + "/",
411+
depth: depth + 1,
412+
});
413+
}
414+
415+
readEntries();
416+
},
417+
() => {
418+
setTimeout(processNext, 0);
419+
}
420+
);
421+
};
422+
423+
readEntries();
424+
} else {
425+
setTimeout(processNext, 0);
426+
}
427+
};
428+
429+
processNext();
430+
} else if (dataTransfer["files"]) {
431+
432+
// Fallback: flat file list
433+
for (let i = 0; i < dataTransfer["files"].length; i++) {
434+
const file = dataTransfer["files"][i];
435+
436+
if (window.FileList && file.name && file.size) {
437+
doFileUpload(file);
438+
} else if (!empty(file.type) && file.size < 1) {
439+
Ext.MessageBox.alert(t('error'), t('error_empty_file_upload'));
440+
win.close();
441+
}
442+
}
443+
444+
if (!this.activeUploads) {
445+
win.close();
446+
}
447+
}
448+
449+
// Close progress window if no uploads detected after delay
450+
setTimeout(function () {
451+
if (!this.activeUploads) {
452+
win.close();
453+
}
454+
}.bind(this), 5000);
419455
},
420456

421457
getTreeNodeListeners: function () {

0 commit comments

Comments
 (0)