user1412659
user1412659

Reputation: 31

Filesystem API - Upload from local drive to local filesystem

Ive read a lot about the filesystem API and HTML5, but i just couldn't find a working solution so i ask you guys:

I want to have a file upload form, drag drop or regular input box doesnt matter, however i want to select a file, and after uploading it should take the file or a whole folder and "upload" it to the filesystem located on the clients computer. The upload is in brackets because i actually want to copy the file/folder to the clients local file system.

Is it even possible? Because i want to make an application, where a user can upload his files such as music or large videos and movies to his local filesystem and edit/watch etc them in my application. I know i have to upload those big files i have to cut them into pieces and load them stacked up, but i just want to start little :)

Thanks in advance

Upvotes: 3

Views: 6215

Answers (2)

pimvdb
pimvdb

Reputation: 154828

There's indeed little information on this subject at the moment, so I put together an example that combines:

  • Using the webkitdirectory attribute on <input type="file">.
    • This allows the user to select a directory using an appropriate dialog box.
  • Using the Filesystem API.
    • This is about the sandboxed filesystem which allows you to store files on the client's machine.
  • Using the File API.
    • This is the API that allows you to read files. The files are accessible through an <input type="file"> element, through a transfer using drag and drop, or through the Filesystem API.

As these are currently only working nicely in Chrome, I used the webkit prefix where necessary.

http://jsfiddle.net/zLna6/3/

The code itself has comments which I hope are clear:

var fs,
    err = function(e) {
        throw e;
    };

// request the sandboxed filesystem
webkitRequestFileSystem(
    window.TEMPORARY,
    5 * 1024 * 1024,
    function(_fs) {
        fs = _fs;
    },
    err
);

// when a directory is selected
$(":file").on("change", function() {
    $("ul").empty();

    // the selected files
    var files = this.files;
    if(!files) return;

    // this function copies the file into the sandboxed filesystem
    function save(i) {
        var file = files[i];

        var text = file ? file.name : "Done!";

        // show the filename in the list
        $("<li>").text(text).appendTo("ul");

        if(!file) return;

        // create a sandboxed file
        fs.root.getFile(
            file.name,
            { create: true },
            function(fileEntry) {
                // create a writer that can put data in the file
                fileEntry.createWriter(function(writer) {
                    writer.onwriteend = function() {
                        // when done, continue to the next file
                        save(i + 1);
                    };
                    writer.onerror = err;

                    // this will read the contents of the current file
                    var fr = new FileReader;
                    fr.onloadend = function() {
                        // create a blob as that's what the
                        // file writer wants
                        var builder = new WebKitBlobBuilder;
                        builder.append(fr.result);
                        writer.write(builder.getBlob());
                    };
                    fr.onerror = err;
                    fr.readAsArrayBuffer(file);
                }, err);
            }, 
            err
        );
    }

    save(0);
});

$("ul").on("click", "li:not(:last)", function() {
    // get the entry with this filename from the sandboxed filesystem
    fs.root.getFile($(this).text(), {}, function(fileEntry) {
        // get the file from the entry
        fileEntry.file(function(file) {
            // this will read the contents of the sandboxed file
            var fr = new FileReader;
            fr.onloadend = function() {
                // log part of it
                console.log(fr.result.slice(0, 100));
            };
            fr.readAsBinaryString(file);
        });
    }, err);
});

Upvotes: 4

apsillers
apsillers

Reputation: 115940

That is not possible, exactly, but your app can still probably work. Reading the file is possible through a file input form element, but writing the file back to disk is where you'll run into trouble.

The two ways your browser can write to disk are 1) downloading a file and 2) the HTML5 filesystem API. Option #1 obviously doesn't let your application choose the destination and option #2 only works with browser-created sandbox filesystems. That restriction might not be a deal-breaker for you -- it just means that the folders that your app uses will be buried somewhere in your browser's data files.

Also, the Filesystem API is currently Chrome-only (but it is an open standard). If you want cross-platform support, maybe you can use IndexedDB. You could use localStorage, but Chrome has a hard 5MB limit, which would be terrible for a media application.

Upvotes: 1

Related Questions