jvilk / BrowserFS

BrowserFS is an in-browser filesystem that emulates the Node JS filesystem API and supports storing and retrieving files from various backends.
Other
3.06k stars 215 forks source link

Serve up only one inidivual file out of a direction with HTTPRequest? #212

Closed Rogerjwilkinson closed 6 years ago

Rogerjwilkinson commented 6 years ago

Hi! I'm a noob through and through, so I hope I'm not wasting people's time with silly questions. I'm trying to modify an online emulator named Retroarch to do a few different things, but for now to this question, I'm trying to get it to automatically "load"/"serve up" a file from the server as soon as the user accesses the page. After days of soul-searching, I finally managed to get it to serve up an index! Like so:

mfs.mount('/home/web_user/retroarch/userdata/content/', new BrowserFS.FileSystem.XmlHttpRequest('../path/index.json', 'path'));

!!! AYYYY

Only problem is, even when I modify the index,json file (which I guess, with the current code I'd just create a new one for each individual file?) to only point to one file in the directory, it seems to create a new one with every file in the directory, which then hangs the app trying to load a 300MB at once as opposed to the 3MB I'm shooting for.

Now, I suspect this is probably because I'm telling the code to create a new file with the 'new' command, but this is the only way I could get it to recognize anything I threw at it. Could somebody please help me out here?

Also, I'm going to use this opportunity to attach a probably "wrong place to ask" question, but I can't find the answer anywhere on google! I was originally using browserfs just by included the browserfs.min.js and .mem files, but to create an index file I had to npm install browserfs - How on earth do I use it from the installed npm instead of including the manual script files? Now that browserfs is "installed" on my server can I just remove the script headers, and it'll all "work"?

Thanks again.

Edit: DRATS! I thought I'd come up with a really clever solution in setting index.json to read-only, but somehow it still overwrote it?

Rogerjwilkinson commented 6 years ago

7 hours later, I think I've at least somewhat narrowed down this problem to "CreatePreloadedFile"? I was able to get to a point with the emscripten port where I had it automatically loading the core it needed to, and it would automount the necessary bianry file to a directory, but when I used the commandline argument to autoload it gave me an app-error:

"[INFO] Loading content file: home/web_user/retroarch/userdata/data.file. Failed to open home/web_user/retroarch/userdata/file.smc: No such file or directory [ERROR] Could not read content file "home/web_user/retroarch/userdata/data.file"."

This was definitely the correct virtual path to the mounted file though. I believe because it isn't actually "loaded" yet? When you navigate to the loaded bianry file in the app, there's a stutter, I assume from retrieving the .json dir. listing, and it doesn't download the binary file until you "launch" it in the app - thus, doesn't exist.

IF I understand correctly (big if), I need to create a function that points to the file on server I'm trying to serve into the FS, and then call that function with preLoad to do this before the emscripten program runs?

Am I at least in the right direction? Thanks for time.

jvilk commented 6 years ago

I'm not 100% familiar with how RetroArch is using BrowserFS, but it's likely similar to what the Internet Archive does. It likely uses AsyncMirror to preload all of the file system data in-memory, which lets Emscripten-compiled emulators access the data synchronously. Thus, if you hand it an XHRFS that points to a directory of files, all of those files will be read into memory before RetroArch begins.

With XHRFS, it will preload all of the files that index.json points to.

I modify the index,json file (which I guess, with the current code I'd just create a new one for each individual file?) to only point to one file in the directory, it seems to create a new one with every file in the directory, which then hangs the app trying to load a 300MB at once as opposed to the 3MB I'm shooting for.

If RetroArch creates a new index.json with all of the files (which you could verify by downloading that file yourself and looking at it), then that's not behavior that BrowserFS controls.

Hope that helps.

jvilk commented 6 years ago

Oh, just read your second post.

You'll need to use AsyncMirror with an InMemoryFileSystem to make the XHRFS files available synchronously. If RetroArch is using an older version of BrowserFS, than the sample code in that documentation won't work; I think you need to run new AsyncMirror(async, sync) followed by .initialize or something like that on the file system. It's kludgey, which is why I overhauled file system construction in the latest version of BFS. :)

So: Use an AsyncMirror that wraps the XHRFS and an InMemoryFileSystem mounted at that location within the MountableFileSystem.

Rogerjwilkinson commented 6 years ago

Oh mate, you are awesome! It was right there in front of me the whole time, retroarch does the async initialize but it calls it before and I guess executes it before calling and mounting the xhr request. Moved that call up to happen at the same time as the bfs async mount, and VOILA.

Thank you so much for your time!!