Javascript 为什么可以';是否无法通过IndexedDB中保存的emscriptens fopen()打开文件?

Javascript 为什么可以';是否无法通过IndexedDB中保存的emscriptens fopen()打开文件?,javascript,c++,c,fetch,emscripten,Javascript,C++,C,Fetch,Emscripten,我正在试用Emscriptens IndexedDB,但无法运行它。无法加载文件,“无法打开文件”。使用EMSCRIPTEN_获取_加载_到_内存,一切正常 通过emscripten的emscripten获取下载文件 通过EMSCRIPTEN\u FETCH\u PERSIST\u文件将文件直接保存到IndexedDB中 稍后将其加载到内存中 建造 如果应用程序希望下载文件以供本地访问,但 不需要立即使用该文件,例如在预加载数据时 为了便于以后访问,最好避免 EMSCRIPTEN_FETCH_L

我正在试用Emscriptens IndexedDB,但无法运行它。无法加载文件,“无法打开文件”。使用EMSCRIPTEN_获取_加载_到_内存,一切正常

  • 通过emscripten的emscripten获取下载文件
  • 通过EMSCRIPTEN\u FETCH\u PERSIST\u文件将文件直接保存到IndexedDB中
  • 稍后将其加载到内存中
  • 建造

    如果应用程序希望下载文件以供本地访问,但 不需要立即使用该文件,例如在预加载数据时 为了便于以后访问,最好避免 EMSCRIPTEN_FETCH_LOAD_TO_内存标志,只传递 改为使用EMSCRIPTEN\u FETCH\u PERSIST\u文件标志。这会导致提取失败 将文件直接下载到IndexedDB,这样可以暂时避免 下载完成后在内存中填充文件。在这个 在这种情况下,onsuccess()处理程序将只报告总数 下载的文件大小,但不包含文件的数据字节

    但是我仍然可以读取数据字节,为什么


    有人能帮我一下吗,我做错了什么?

    EMSCRIPTEN\u FETCH\u PERSIST\u FILE
    实际上做了两件事:

  • 检查文件是否已存储在IndexDB中。如果是,从那里检索它,并且根本不打扰服务器
  • 如果文件不在本地IndexDB中,请从服务器下载并在那里缓存
  • 特别是,几乎没有缓存控制:您可以删除缓存版本,但仅此而已

    答复 所以,看起来您不应该使用IDBFS来访问获取的文件。改为使用Fetch库,它将使用缓存版本,而不进行任何网络往返

    -s FETCH\u DEBUG
    添加到编译行也可能很有用

    但为什么它不起作用呢? 理解的先决条件:通读以理解“数据库”和“对象存储”

    查看my brower的开发者控制台中的“存储”选项卡:

    • 安装在
      /data foo bar
      上的IDBF提供对名为
      /data foo bar
      的数据库的访问。具体地说,它的
      文件\u数据
      对象存储(请参阅)。这里的命名是任意的和硬编码的。存储在
      /data foo bar
      文件夹中的文件存储在该对象存储中的
      /data foo bar/my file.txt
      等键中
    • 特别是,您不能访问任意IndexDB数据库或对象存储
    • 另一方面,将库文件提取到
      emscripten_文件系统
      数据库,即
      文件
      对象存储。同样,名称看起来是任意的,并且是硬编码的
    因此,不能通过IDBFS访问Fetch的缓存,因为IDBFS使用不同的命名约定访问不同数据库中的不同存储对象

    例如,以下是
    FS.writeFile('/data/my file.txt',hello')
    在我的Firefox中产生的结果:

    下面是提取缓存所在的位置:


    不幸的是,我不知道为什么
    http://localhost:8000/test.txt
    显示为空对象。

    @yeputons:Thxs供您解释!这有助于我理解我的观察结果

  • 我阅读了IDBFS的内容,其中有/tmp、/home、/dev、/proc和/data文件夹,但没有test.txt文件
  • 如果我清除浏览器缓存,然后重新加载网站,则fetch->numBytes=0和下一次重新加载test.txt的数据都可用

  • 因此,结论是,正如您已经提到的,不要混合使用“获取缓存”和IDBF。如果使用EMSCRIPTEN\u FETCH\u PERSIST\u文件,则必须提取文件两次,1。下载并将其保存在“获取缓存”和稍后的某个时间2。将其读入内存并通过fetch->data访问。

    您没有提供
    shell.html
    。如果将
    -o index.js--shell文件shell.html
    替换为
    -o index.html
    ,问题是否会重现?嗨,是的!我只是用
    -o index.html
    单独检查了一下。但不幸的是没有什么区别。
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    
    #include <emscripten.h>
    #include <emscripten/fetch.h>
    
    using namespace std;
    
    void downloadSucceeded(emscripten_fetch_t *fetch)
    {
        printf("URL %s\n", fetch->url);
        printf("bytes %llu\n", fetch->numBytes);
    
        FILE *file = fopen("/data/test.txt", "r"); // also tried it with 'test.txt', '/test.txt', 'data/test.txt'
        if (!file) {
            printf("cannot open file\n");
            return;
        }
    
        fclose (file);
    
        emscripten_fetch_close(fetch);
    }
    
    void downloadFailed(emscripten_fetch_t *fetch) {
      printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
      emscripten_fetch_close(fetch);
    }
    
    extern "C" {
    void EMSCRIPTEN_KEEPALIVE download() {
        cout << "download" << endl;
    
        emscripten_fetch_attr_t attr;
        emscripten_fetch_attr_init(&attr);
        strcpy(attr.requestMethod, "GET");
        attr.attributes = EMSCRIPTEN_FETCH_PERSIST_FILE;
        attr.onsuccess = downloadSucceeded;
        attr.onerror = downloadFailed;
        emscripten_fetch(&attr, "http://localhost/test.txt");
    }
    }
    
    int main() {
        cout << "main" << endl;
        EM_ASM(
            FS.mkdir('/data');
            FS.mount(IDBFS, {}, '/data');
    
            FS.syncfs(true, function (err) {
                console.log("syncfs");
                Module._download();
                assert(!err);
            });
        );
    
        emscripten_exit_with_live_runtime();
    }
    
    main
    syncfs
    download
    URL http://localhost/test.txt
    bytes 185
    cannot open file
    
    emcc code.cpp -o index.js --shell-file shell.html -lidbfs.js -s EXPORTED_FUNCTIONS="['_main','_download']" -s FETCH=1 -O3
    
    EM_ASM(
        var l = FS.readdir("/");
        for(var i in l) { 
            var item = l[i];
            console.log(item);
        }
        );