Skip to content

Repository files navigation

FileAPI — a set of tools for working with files.

~~~ DEMO ~~~ user pic ~~~

Support

  • Multiupload: all browsers that support HTML5 or Flash
  • Drag'n'Drop upload: files (HTML5) & directories (Chrome 21+)
  • Chunked file upload (HTML5)
  • Upload one file: all browsers
  • Working with Images: IE6+, FF 3.6+, Chrome 10+, Opera 11.1+, Safari 5.4+
    • crop, resize, preview & rotate (HTML5 or Flash)
    • auto orientation by exif (HTML5, if include FileAPI.exif.js or Flash)

Example

<spanclass="js-fileapi-wrapper" style="position: relative;"><inputid="user-files" type="file" multiple/></span><divid="preview-list"></div>
varinput=document.getElementById('user-files');varpreviewNode=document.getElementById('preview-list');// Drag'n'DropFileAPI.event.dnd(previewNode,function(over){$(this).css('background',over ? 'red' : '');},function(files){// ..});FileAPI.event.on(input,'change',function(evt){varfiles=FileAPI.getFiles(evt.target);// or FileAPI.getFiles(evt)// filteringFileAPI.filterFiles(files,function(file,info){if(/image/.test(file.type)&&info){returninfo.width>=320&&info.height>=240;}else{returnfile.size>128;}},function(fileList,ignor){if(ignor.length){// ...}if(!fileList.length){// empty file listreturn;}// do previewvarimageList=FileAPI.filter(fileList,function(file){return/image/.test(file.type);});FileAPI.each(imageList,function(imageFile){FileAPI.Image(imageFile).preview(100,120).get(function(err,image){if(err){// ...}else{previewNode.appendChild(image);}});});// upload on servervarxhr=FileAPI.upload({url: '...',data: {foo: 'bar'},// POST-data (iframe, flash, html5)headers: {'x-header': '...'},// request headers (html5)files: {files: FileAPI.filter(fileList,function(file){return!/image/.test(file.type);}),pictures: imageList},imageTransform: {maxWidth: 1024,maxHeight: 768},imageAutoOrientation: true,fileprogress: function(evt){// (flash, html5)varpercent=evt.loaded/evt.total*100;// ...},progress: function(evt){// (flash, html5)varpercent=evt.loaded/evt.total*100;// ...},complete: function(err,xhr){// ...}});});});

HTML structure (templates)

API

Events

  • FileAPI.event.on(el:HTMLElement, eventType:String, fn:Function)
  • FileAPI.event.off(el:HTMLElement, eventType:String, fn:Function)
  • FileAPI.event.one(el:HTMLElement, eventType:String, fn:Function)
  • FileAPI.event.dnd(el:HTMLElement, onHover:Function, onDrop:Function)
  • jQuery('#el').dnd(onHover, onDrop)

FileAPI.Image

  • .crop(width[, height])
  • .crop(x, y, width[, height])
  • .resize(width[, height])
  • .resize(width, height, type:Enum(min,max,preview))
  • .preview(width[, height])
  • .rotate(deg)
  • .get(fn:Function)

Utils

  • FileAPI.KB
  • FileAPI.MB
  • FileAPI.GB
  • FileAPI.TB
  • FileAPI.support.html5:Boolean
  • FileAPI.support.cors:Boolean
  • FileAPI.support.dnd:Boolean
  • FileAPI.support.flash:Boolean
  • FileAPI.support.canvas:Boolean
  • FileAPI.support.dataURI:Boolean
  • FileAPI.support.chunked:Boolean
  • FileAPI.each(obj:Object|Array, fn:function, context:Mixed)
  • FileAPI.extend(dst:Object, src:Object):Object
  • FileAPI.filter(list:Array, iterator:Function):Array
  • FileAPI.isFile(file:Mixed):Boolean
  • FileAPI.toBinaryString(str:Base64):String

FileAPI.getFiles

FileAPI.event.on('#my-file-1','change',onSelect);// or jQuery$('#my-file-2').on('change',onSelect);functiononSelect(evt/**Event*/){// (1) extract fileList from eventvarfiles=FileAPI.getFiles(evt);// (2) or sovarfiles=FileAPI.getFiles(evt.target);}

FileAPI.getDropFiles

functiononDrop(evt){FileAPI.getDropFiles(evt,function(files){if(files.length){// ...}});}// ORvarel=document.getElementById('el');FileAPI.event.dnd(el,function(over/**Boolean*/,evt/**Event*/){el.style.background=over ? 'red' : '';},function(files/**Array*/,evt/**Event*/){// ...});

FileAPI.getInfo

FileAPI.getInfo(imageFile/**File*/,function(err/**Boolean*/,info/**Object*/){if(!err){switch(info.exif.Orientation){// ...}}});// ...FileAPI.addInfoReader(/^image/,function(file/**File*/,callback/**Function*/){// http://www.nihilogic.dk/labs/exif/exif.js// http://www.nihilogic.dk/labs/binaryajax/binaryajax.jsFileAPI.readAsBinaryString(file,function(evt){if(evt.type=='load'){varbinaryString=evt.result;varoFile=newBinaryFile(binaryString,0,file.size);varexif=EXIF.readFromBinaryFile(oFile);callback(false,{'exif': exif||{}});}elseif(evt.type=='error'){callback('read_as_binary_string');}elseif(evt.type=='progress'){// ...}});});

FileAPI.filterFiles

FileAPI.filterFiles(files,function(file,info){if(/image/.test(file.type)&&info){returninfo.width>320&&info.height>240;}returnfile.size<10*FileAPI.MB;},function(result,ignor){// ...});

FileAPI.readAsImage, FileAPI.readAsDataURL (FileAPI.readAsBinaryString)

FileAPI.readAsImage(file,function(evt){if(evt.type=='load'){varimages=document.getElementById('images');images.appendChild(evt.result);}else{// ...}});FileAPI.readAsDataURL(file,function(evt){if(evt.type=='load'){// successvarresult=evt.result;}elseif(evt.type=='progress'){varpr=evt.loaded/evt.total*100;}else{// error}});

FileAPI.upload

varxhr=FileAPI.upload({url: '...',data: {foo: 'bar'},headers: {'x-header': '...'},files: {images: FileAPI.filter(files,function(file){return/image/.test(file.type);}),customFile: {file: 'generate.txt',blob: customFileBlob}},chunkSize: 0,// or chunk size in bytes, eg: FileAPI.MB*.5 (html5)chunkUploadRetry: 0,// number of retries during upload chunks (html5)imageTransform: {maxWidth: 1024,maxHeight: 768},imageAutoOrientation: true,prepare: function(file,options){// prepare options for current fileoptions.data.filename=file.name;},upload: function(xhr,options){// start uploading},fileupload: function(xhr,options){// start file uploading},fileprogress: function(evt){// progress file uploadingvarfilePercent=evt.loaded/evt.total*100;},filecomplete: function(err,xhr){if(!err){varresponse=xhr.responseText;}},progress: function(evt){// total progress uploadingvartotalPercent=evt.loaded/evt.total*100;},complete: function(err,xhr){if(!err){// Congratulations, the uploading was successful!}}});

imageTransform

  • width:Number
  • height:Number
  • preview:Boolean
  • maxWidth:Number
  • maxHeight:Number
  • rotate:Number
FileAPI.upload({// ..imageOriginal: false,// don't send original on serverimageTransform: {// (1) Resize to 120x200resize: {width: 120,height: 200}// (2) create preview 320x240thumb: {width: 320,height: 240,preview: true}// (3) Resize by max sidemax: {maxWidth: 800,maxHeight: 600}// (4) Custom resizecustom: function(info,transform){returntransform.crop(100,100,300,200).resize(100,50);}}});

imageAutoOrientation

// (1) all imagesFileAPI.upload({// ..imageAutoOrientation: true});// (2) or soFileAPI.upload({// ..imageAutoOrientation: true,imageTransform: {width: ..,height: ..}});// (3) or soFileAPI.upload({// ..imageTransform: {rotate: 'auto'}});// (4) only "800x600", original not modifiedFileAPI.upload({// ..imageTransform: {"800x600": {width: 800,height: 600,rotate: 'auto'}}});

Flash settings

<script>varFileAPI={// @requiredstaticPath: '/js/'// @default: "./"// @optional,flashUrl: '/js/FileAPI.flash.swf'// @default: FileAPI.staticPath + "FileAPI.flash.swf",flashImageUrl: '/js/FileAPI.flash.image.swf'// @default: FileAPI.staticPath + "FileAPI.flash.image.swf"};</script><scriptsrc="/js/FileAPI.min.js"></script>

Flash-request (FileReference)

The following sample HTTP POST request is sent from Flash Player to a server-side script if no parameters are specified:

 POST /handler.cfm HTTP/1.1
Accept: text/*
Content-Type: multipart/form-data;
boundary=----------Ij5ae0ae0KM7GI3KM7
User-Agent: Shockwave Flash
Host: www.example.com
Content-Length: 421
Connection: Keep-Alive
Cache-Control: no-cache
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Filename"
MyFile.jpg
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Filedata"; filename="MyFile.jpg"
Content-Type: application/octet-stream
FileDataHere
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Upload"
Submit Query
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--

Chunked file upload (html5)

FileAPI.upload({url: '...',files: fileList,chunkSize: .5*FileAPI.MB// 512KB,chunkUploadRetry: 1,complete: function(err,xhr){}});

Client and server communicate to each other using the following HTTP headers and status codes.

Client explicitly sets the following headers:

Any other headers are set by a target browser and are not used by client. Library does not provide any facilities to track a file uniqueness across requests, it's left on developer's consideration.

Client recognizes the following response codes:

  • 200, 201 - chunk is successfully saved
  • 416, 500 - recoverable error, library tries to resend chunk 'chunkUploadRetry' times then fails

All the other codes - fatal error, user's involvement is recommend.


{name: 'fileName',type: 'mime-type',size: 'fileSize'}

XMLHttpRequest

{status: Number,statusText: Number,readyState: Number,response: Blob,responseXML: XML,responseText: String,responseBody: String,getResponseHeader: function(name/**String*/)/**String*/{},getAllResponseHeaders: function()/**Object*/{},abort: function(){}}

Cross-Domain upload-controller headers

<?header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type'); // and other custom headersheader('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); // a comma-separated list of domainsheader('Access-Control-Allow-Credentials: true');
if( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ){
exit;
}
if( $_SERVER['REQUEST_METHOD'] == 'POST' ){
// ...
}
?>

iframe

POST-query

/controller.php
?foo=bar
&images=...
&callback=...

POST-response

<script type="text/javascript">
(function (ctx, jsonp){
if( ctx && ctx[jsonp] ){
ctx[jsonp](<?=$statusCode/*200 — OK*/?>, "<?=addslashes($statusText)?>", "<?=addslashes($response)?>");
}
})(this.parent, "<?=htmlspecialchars($_POST['callback'])?>");
</script>

HTML structure (templates)

Default

<spanclass="js-fileapi-wrapper" style="position: relative; display: inline-block;"><inputname="files" type="file" multiple/></span>

Button

<style>
.upload-btn {
width:130px;
height:25px;
overflow: hidden;
position: relative;
border:3px solid #06c;
border-radius:5px;
background:#0cf;
}
.upload-btn:hover {
background:#09f;
}
.upload-btn__txt {
z-index:1;
position: relative;
color:#fff;
font-size:18px;
font-family:"Helvetica Neue";
line-height:24px;
text-align: center;
text-shadow:01px1px#000;
}
.upload-btn__inp {
top:-10px;
right:-40px;
z-index:2;
position: absolute;
cursor: pointer;
opacity:0;
filter:alpha(opacity=0);
font-size:50px;
}
</style><divclass="upload-btn js-fileapi-wrapper"><divclass="upload-btn__txt">Upload files</div><inputclass="upload-btn__inp" name="files" type="file" multiple/></div>

Link

<style>
.upload-link {
color:#36c;
display: inline-block;
*zoom:1;
*display: inline;
overflow: hidden;
position: relative;
padding-bottom:2px;
text-decoration: none;
}
.upload-link__txt {
z-index:1;
position: relative;
border-bottom:1px dotted #36c;
}
.upload-link:hover .upload-link__txt {
color:#f00;
border-bottom-color:#f00;
}
.upload-link__inp {
top:-10px;
right:-40px;
z-index:2;
position: absolute;
cursor: pointer;
opacity:0;
filter:alpha(opacity=0);
font-size:50px;
}
</style><aclass="upload-link js-fileapi-wrapper"><spanclass="upload-link__txt">Upload photo</span><inputclass="upload-link__inp" name="photo" type="file" accept=".jpg,.jpeg,.gif" /></a>

Changelog

    • FileAPI.withCredentials: true
  • #90: Fixed progress event

1.2.5

  • #86: Smarter upload recovery
  • #87: Fixed upload files into browsers that do not support FormData
  • Fixed support "accept" attribute for Flash.
  • Fixed detection of HTML5 support for FireFox 3.6
    • FileAPI.html5 option, default "true"

1.2.4

  • Fixed auto orientation image by EXIF (Flash)
  • Fixed image dimensions after rotate (Flash)
  • #82: "undefined" data-fields cause exceptions
  • #83: Allow requests without files
  • #84: Fixed connection abort when waiting for connection recovery

1.2.3

  • #77: Fixed flash.abort(), #75
    • FileAPI.addMime
    • FileAPI.accept — fallback for flash.

1.2.2

  • #67: Added correct httpStatus for upload fail, #62
  • #68 Added "Content-Type" for chunked upload, #65
  • #69: Fixed network down recovery
  • Fixed progress event, #66
  • Increase flash stage size, #73
    • array index from POST-param "name", #72
    • dependency on FileAPI.Image for FileAPI.Flash

1.2.1

1.2.0

  • #57: Chunked file upload

1.1.0

  • #54: added FileAPI.flashUrl and FileAPI.flashImageUrl

1.0.1

  • #51: remove circular references from file-objects (Flash transport)
  • added changelog

1.0.0

  • first release

About

FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors