Javascript FileSaver saves empty files after writing a large number of files

Background

I am working on an internal project that can basically generate video on the client side, but since there are no JavaScript video encoders that I know of, I just export each frame separately. I need to avoid uploading to the server; it all happens on the client side.

Implementation

I use this FileSaver.js (more precisely, the Chrome Web File File website API) to save a large number of PNG generated HTML5 canvas. I installed Chrome to automatically download to a specific folder, so when I click "Save", it just takes and saves something like 20 images per second. This works great for my purposes.

If I could use JSZip to compress all these frames into one file before offering it to the client for saving, I would, but I didn’t even try, because the browser does not have enough memory to generate ~ 8000 640x480 PNG, and then it compresses them.

Problem

The problem is that after a certain number of images, each downloaded file is empty. Chrome even starts telling me in the download bar that the file is 0 bytes. Repeating in the same project with the same export settings, an empty start starts exactly at the same time. For example, with one project, I can save the first 5494 frames before it slams. (I know this is an insanely large number, but I can not help it.) I tried to set a delay of 10 ms between saves, but this had no effect. I have not tried a big delay because it takes a very long time to export.

I checked blob.size and it was never null. I suspect that this exceeds a certain quota, but there were no errors; it simply cannot silently either write to the sandbox or copy the file to a location specified by the user.

Questions

How can I detect these empty saves? Prevent them? Is there a better way to do this? Am I just screwed up?


EDIT: Actually, after debugging FileSaver.js, I realized that it doesn't even use webkitRequestFileSystem; he comes back when he gets here:

if (can_use_save_link) { object_url = get_object_url(blob); save_link.href = object_url; save_link.download = name; if (click(save_link)) { filesaver.readyState = filesaver.DONE; dispatch_all(); return; } } 

So it looks like it doesn't even use the FileSystem API, so I have no idea how to clear the repository before it is fully loaded.


EDIT 2: I tried to move the if (can_use_save_link) block inside the "writer.onwriteend" function and change it to this:

 if (can_use_save_link) { save_link.href = file.toURL(); save_link.download = name; click(save_link); }else{ target_view.location.href = file.toURL(); } 

As a result, I can save all 8260 files (about 1.5 GB), since now it uses storage with a quota. Previously, files were not displayed in the HTML5 file system, because I assume that you did not need to place them there if the anchor element supported the download attribute.

I was also able to comment on the code adding ".download" to the file name, and I had to provide an empty anonymous function as an argument for both instances of "file.remove ()".

+4
source share
2 answers

I finished modifying FileSaver.js (see "EDIT 2" in the original post).

0
source

Use JSZip, it will not use too much memory if you disable compression (this is the default value). To manually disable compression, be sure to pass compression: "STORE" when you call zip.generate() .

0
source

All Articles