node-file-api / file-api

HTML5 FileAPI for Node.js
Apache License 2.0
54 stars 10 forks source link

file-api

HTML5 FileAPI implemented in Node.js

The goal here is to be able to use this in connection with jsdom to create test utilities, possibly scraping utilities, ultimately an API-driven browser written in Node.

Usage

Install:

npm install file-api

Use:

var FileAPI = require('file-api')
  , File = FileAPI.File
  , FileList = FileAPI.FileList
  , FileReader = FileAPI.FileReader
  ;

API

Since HTML5 FileAPI has been described by the W3C (terse, technical) and Mozilla Developer Center (understandable, end-user-oriented) in detail, I'll just highlight the differences:

FormData

FormData on MDN

Has the special method setNodeChunkedEncoding()

File

In the browser, File has no constructor. In Node, it does.

node-mime is used for extension-based automatic ContentType detection (uses name if available, or path if not)

File(StringUriPath)

var file = new File("./files/myfile.txt");

File({ buffer: Node.Buffer })

var file = new File({ 
  name: "abc-song.txt",   // required
  type: "text/plain",     // optional
  buffer: new Buffer("abcdefg,hijklmnop, qrs, tuv, double-u, x, y and z")
});

File({ stream: Node.ReadStream })

var file = new File({
  name: "abc-song.txt",       // required
  type: "text/plain",         // optional
  stream: new EventEmitter()  // a read stream (emits `error`, `data`, `end`)
});

process.nextTick(function () {
  file.stream.emit('data', "abcdefg,hijklmnop, qrs, tuv, double-u, x, y and z");
  file.stream.emit('end');
});

File(Object)

var file = new File({
  path: "./files/myfile.txt",   // path of file to read

  buffer: Node.Buffer,          // use this Buffer instead of reading file

  stream: Node.ReadStream,      // use this ReadStream instead of reading file

  name: "SomeAwesomeFile.txt",  // optional when using `path`
                                // must be supplied when using `Node.Buffer` or `Node.ReadStream`

  type: "text/plain",           // generated based on the extension of `name` or `path`

  jsdom: true,                  // be DoM-like and immediately get `size` and `lastModifiedDate`
                                // [default: false]

  async: true,                  // use `fs.stat` instead of `fs.statSync` for getting 
                                // the `jsdom` info
                                // [default: false]

  lastModifiedDate: fileStat.mtime.toISOString(),

  size: fileStat.size || Buffer.length
);

FileReader

FileReader.setNodeChunkedEncoding() is a non-standard method which hints that the FileReader should chunk if possible

I.E. The file will be sent with the header Transfer-Encoding: chunked

The default is false since many webservers do not correctly implement the standard correctly, and hence do not expect or accept Transfer-Encoding: chunked from clients.

FileReader.on is a non-standard alias of addEventListener

EventTarget.target.nodeBufferResult is a non-standard property which is a Node.Buffer instance of the data.

FileReader.on('data', fn) is a non-standard event which passes a Node.Buffer chunk each time the progress event is fired.

var fileReader = new FileReader();

fileReader.setNodeChunkedEncoding(true || false);
fileReader.readAsDataURL(new File('./files/my-file.txt'));

// non-standard alias of `addEventListener` listening to non-standard `data` event
fileReader.on('data', function (data) {
  console.log("chunkSize:", data.length);
});

// `onload` as listener
fileReader.addEventListener('load', function (ev) {
  console.log("dataUrlSize:", ev.target.result.length);
});

// `onloadend` as property
fileReader.onloadend', function () {
  console.log("Success");
});

FileList

The browser has no constructor for this. Node has two.

new FileList(f1, f2, ...)

var fileList = new FileList(file1, file2, file3);

new FileList([f1, f2])

var files = [
    new File('./files/blob.bin'),
    new File('./files/image.jpg'),
    new File('./files/readme.txt')
  ],
  fileList;

fileList = new FileList(files);

Formal Documentation

W3C

Mozilla Developer Center:

TODO

//
// TODO
//
// HTML5 File URI should be implemented
//   will need non-ahr 301-handling requester not prevent circular dep
//
// File should be a subclass of Blob
//
// jsdom EventTarget // http://aptana.com/reference/html/api/EventTarget.html
//    target.result
// 
// jsdom ProgressEvent // http://www.w3.org/TR/progress-events/
//    lengthComputable
//    loaded
//    total
//    initProgressEvent