I'm trying out the Emscriptens IndexedDB, but can't get it running. The file can't be loaded, "cannot open file". With EMSCRIPTEN_FETCH_LOAD_TO_MEMORY everthing works fine.
- Download file via emscripten's emscripten_fetch_t
- Save file directly in IndexedDB via EMSCRIPTEN_FETCH_PERSIST_FILE
- Load it later into memory
#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();
}
Output
main
syncfs
download
URL http://localhost/test.txt
bytes 185
cannot open file
Built
emcc code.cpp -o index.js --shell-file shell.html -lidbfs.js -s EXPORTED_FUNCTIONS="['_main','_download']" -s FETCH=1 -O3
If an application wants to download a file for local access, but does not immediately need to use the file, e.g. when preloading data up front for later access, it is a good idea to avoid the EMSCRIPTEN_FETCH_LOAD_TO_MEMORY flag altogether, and only pass the EMSCRIPTEN_FETCH_PERSIST_FILE flag instead. This causes the fetch to download the file directly to IndexedDB, which avoids temporarily populating the file in memory after the download finishes. In this scenario, the onsuccess() handler will only report the total downloaded file size, but will not contain the data bytes to the file.
But I can still read the data bytes, why?
Can some help me, what I'm doing wrong?

