当文件更改和页面重新加载时,从存储在indexedDB中的文件句柄加载的文件不会更新

问题描述 投票:0回答:1

使用此处介绍的方法:

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>
javascript filereader indexeddb page-refresh
1个回答
0
投票

通过

DataTransferItem
getAsFile()
DataTransfer
files
列表返回的对象是
File
对象,它不等同于文件句柄,而是代表文件本身的数据 -
File
在网络平台 API 中基本上只是一个带有名称的
Blob

因此,当您调用

idbStore()
传递文件时,您实际上是将文件的 contents 存储到数据库中。当存储发生时,实现将吸收文件的内容并将其存储在数据库中。这就是为什么您在重新加载页面时看不到新数据的原因。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.