gpt4 book ai didi

javascript - HTML5 ondrop 事件在 zip.js 完成操作之前返回

转载 作者:太空狗 更新时间:2023-10-29 13:15:51 24 4
gpt4 key购买 nike

我的问题的症结在于我需要异步使用 datatransferitemlist,这与规范中描述的功能不一致,即一旦事件结束,您将被锁定在 dataTransfer.items 集合之外。

https://bugs.chromium.org/p/chromium/issues/detail?id=137231 http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#drag-data-store

案犯如下。在下面对我的问题和想法进行了更详细的描述。

drophandler: function(event) {
event.stopPropagation();
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
zip.workerScriptsPath = "../bower_components/zip.js/WebContent/";
zip.useWebWorkers = false; // Disabled because it just makes life more complicated
// Check if files contains just a zip
if (event.dataTransfer.files[0].name.match(/(?:\.([^.]+))?$/) == 'zip') {
var reader = new FileReader();
that = this;
reader.onload = function(e) {
that.fire('zipuploaded', e.target.result.split(',')[1]);
}
reader.readAsDataURL(event.dataTransfer.files[0]);
// Rev up that in browser zipping
} else {
var that = this;
var items = event.dataTransfer.items;
// Async operation, execution falls through from here
zip.createWriter(new zip.Data64URIWriter(), function(writer) {
(function traverse(list, path, i, depth) {
return new Promise(function(resolve, reject) {
var item;
if (depth == 0) {
if (i == list.length) {
writer.close(function(uri) {
that.fire('zipuploaded', uri.split(',')[1]); // Just the base64, please
fulfill(1);
return;
});
} else {
console.log(i);
console.log(list);
var item = list[i].webkitGetAsEntry();
}
} else {
if (i == list.length) {
resolve(0);
return;
} else {
item = list[i];
}
}
if (item.isFile) {
item.file(function(file) {
// Zipping operations done asynchronously, it'll fail by roughly the second operation
writer.add(path + file.name, zip.BlobReader(file), function() {
traverse(list, path, i + 1, depth).then(resolve(0)); // Next item
});
});
} else if (item.isDirectory) {
var dirReader = item.createDirReader();
dirReader.readEntries(function(entries) {
// Operate on child folder then the next item at this level
traverse(entries, path + item.name + "/", 0, depth + 1).then(function() {
traverse(list, path, i + 1, depth).then(resolve(0));
});
});
}
});
})(items, "", 0, 0); // Begin with datatransferitemlist, 0th element, depth 0
});
this.$.uploadarea.classList.remove('highlightdrag');
}
// When we exit it kills the event.dataTransfer.items
},

我正在使用与 HTML5 DnD API 异步的 zip.js。ondrop 事件在异步 zip.createWriter/writer.add 操作完成之前结束。我可以想到四种方法来解决这个问题,尽管我不知道如何实现它们中的任何一种,并希望得到一些建议。

  1. 阻塞直到 createWriter 完成。 (阻止 javascript?呃)
  2. 防止 ondrop 将我锁定在 dataTransfer.items 之外(这似乎是为了安全不太可能)
  3. 首先同步复制出 dataTransfer.items 的内容(可能很慢)
  4. 同步执行所有操作(不要认为 zip.js 允许这样做,JsZip 允许,但我放弃了它,因为它对大文件集有其自身的限制)

最佳答案

HTML5 DnD 按预期工作。问题是,当添加多个文件时,如果您在之前完成之前添加一个文件,zip.js 会静默中断。这可以通过连续调用 writer.add 来解决。

该代码段可能无效,请参阅此 pen相反。

此示例将拖放文件的结构扁平化,然后将其添加到 zip 系列

function mes(it) {
const m = document.querySelector('#mes')
return m.textContent = it + '\n' + m.textContent
}

function read(items) {
return Promise.all(items.map(item => {
if (item.isFile) return [item]
return new Promise(resolve => item.createReader().readEntries(resolve))
.then(entries => {
entries.forEach(it => it.path = item.path + '/' + it.name)
return read(entries)
})
})).then(entries => entries.reduce((a, b) => a.concat(b)))
}

function handleResult(blob){
const res = document.querySelector('#result')
res.download = 'files.zip'
res.href = window.URL.createObjectURL(blob)
res.textContent = 'download zipped file'
}

function handleItems(items){
mes(items.length)
items.forEach(item => item.path = item.name)
const initZip = new Promise(resolve =>
zip.createWriter(new zip.BlobWriter, resolve)
)
const getFiles = read(items).then(entries => {
return Promise.all(entries.map(entry =>
new Promise(resolve =>
entry.file(file => {
file.path = entry.path
resolve(file)
})
)
))
})
return Promise.all([getFiles, initZip]).then(([files, writer]) =>
files.reduce((current, next) =>
current.then(() =>
new Promise(resolve => {
mes(next.path)
writer.add(next.path, new zip.BlobReader(next), resolve)
})
)
, Promise.resolve())
.then(() => writer.close(handleResult))
)
}

zip.useWebWorkers = false
const drop = document.querySelector('#drop');

['dragover', 'drop'].forEach(name =>
drop.addEventListener(name, ev => ev.preventDefault())
)
drop.addEventListener('drop', ev => {
const items = [].slice.call(ev.dataTransfer.items)
.map(item => item.webkitGetAsEntry())
return handleItems(items)
})
html, body, #drop {
height: 100%;
width: 100%;
}
<script src="http://gildas-lormeau.github.io/zip.js/demos/zip.js"></script>
<script src="http://gildas-lormeau.github.io/zip.js/demos/deflate.js"></script>


<div id="drop">
Drop here!
<br>
<a id="result"></a>
</div>
<pre id="mes"></pre>

jszip比这容易得多,你可能想试一试。

关于javascript - HTML5 ondrop 事件在 zip.js 完成操作之前返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39370004/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com