使用这里介绍的方法:
https://stackoverflow.com/a/65938910/3825996
我已经创建了一个网页,您可以在任何地方放置文件,内容将显示。放置后,文件的句柄存储在indexedDB中,当页面刷新时,最后一个文件将再次打开并显示。
我希望如果我更改文件并重新加载页面,会显示新内容,但实际上没有。然而,如果我拖放更改的文件,它将正确显示更改的内容。
在Chrome中,我也做了“清空缓存并硬重新加载”,但它仍然显示旧文件内容。
为什么会发生这种情况?文件句柄是否存储了完整的文件?我可以做些什么,以便在刷新后重新加载更改的文件?
下面是代码:(不作为HTML代码段工作)
<html>
<head></head>
<body>
<div id="display"></div>
<script>
// stolen from https://www.npmjs.com/package/idb-keyval
function promisifyRequest(request) {
return new Promise((resolve, reject) => {
request.oncomplete = request.onsuccess = () => resolve(request.result);
request.onabort = request.onerror = () => reject(request.error);
});
}
function createStore(dbName, storeName) {
const request = indexedDB.open(dbName);
request.onupgradeneeded = () => request.result.createObjectStore(storeName);
const dbp = promisifyRequest(request);
return (txMode, callback) => dbp.then((db) => callback(db.transaction(storeName, txMode).objectStore(storeName)));
}
let defaultGetStoreFunc;
function defaultGetStore() {
if (!defaultGetStoreFunc) {
defaultGetStoreFunc = createStore('keyval-store', 'keyval');
}
return defaultGetStoreFunc;
}
function idbLoad(key, customStore = defaultGetStore()) {
return customStore('readonly', (store) => promisifyRequest(store.get(key)));
}
function idbStore(key, value, customStore = defaultGetStore()) {
return customStore('readwrite', (store) => {
store.put(value, key);
return promisifyRequest(store.transaction);
});
}
function makeKey(domElement) {
return 'lastOpened-' + domElement.tagName + "-" + domElement.id;
}
async function handleFile(domElement, file) {
await idbStore(makeKey(domElement), file);
const reader = new FileReader();
reader.onload = function (e) {
domElement.dispatchEvent(
new CustomEvent("handlefilecontent", { detail: e.target.result })
);
};
reader.readAsText(file);
}
function dropHandler(ev) {
ev.preventDefault();
if (ev.dataTransfer.items) {
[...ev.dataTransfer.items].forEach((item, i) => {
if (item.kind === "file") {
const file = item.getAsFile();
handleFile(ev.currentTarget, file);
}
});
} else {
[...ev.dataTransfer.files].forEach((file, i) => {
handleFile(ev.currentTarget, file);
});
}
}
function dragOverHandler(ev) {
ev.preventDefault();
}
async function checkLastOpened(domElement) {
try {
let file = await idbLoad(makeKey(domElement));
if (file) {
handleFile(domElement, file)
}
} catch (error) {
alert(error.name, error.message);
}
}
function dragDropInitialize(domElement, callback) {
domElement.addEventListener("drop", dropHandler)
domElement.addEventListener("dragover", dragOverHandler)
domElement.addEventListener("handlefilecontent", (ev) => { callback(ev.detail) })
checkLastOpened(domElement)
}
dragDropInitialize(document.body, (content) => {
document.getElementById("display").innerHTML = content
})
</script>
</body>
</html>
字符串
1条答案
按热度按时间yks3o0rb1#
通过
DataTransferItem
的getAsFile()
或DataTransfer
的files
列表返回的对象都是File
对象,它们并不等价于文件句柄,而是代表文件本身的数据--web平台API中的一个File
基本上只是一个有名字的Blob
。因此,当你调用
idbStore()
传递文件时,你实际上是在将文件的内容存储到数据库中。当存储发生时,实现将把文件的内容存储到数据库中。这就是为什么当你重新加载页面时,你看不到新的数据。