Skip to content

Commit

Permalink
Merge pull request #57 from wingedfox/master
Browse files Browse the repository at this point in the history
Resumable upload
  • Loading branch information
RubaXa committed Feb 7, 2013
2 parents 708ca53 + 167ae7c commit cc4c963
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 46 deletions.
4 changes: 2 additions & 2 deletions FileAPI.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# FileAPI — a set of tools for working with files.
# FileAPI — a set of tools for working with files.


<p align="center">
Expand Down Expand Up @@ -220,7 +220,7 @@ function onDrop(evt){

var el = document.getElementById('el');
FileAPI.event.dnd(el, function (over/**Boolean*/, evt/**Event*/){
el.style.background = ever ? 'red' : '';
el.style.background = over ? 'red' : '';
}, function (files/**Array*/, evt/**Event*/){
// ...
});
Expand Down
2 changes: 1 addition & 1 deletion lib/FileAPI.Flash.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
* FileAPI fallback to Flash
*
* @flash-developer "Vladimer Demidov" <v.demidov@corp.mail.ru>
Expand Down
19 changes: 18 additions & 1 deletion lib/FileAPI.Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
}
},

toData: function (fn){
toData: function (fn, options){
if( !api.support.html5 ){
api.log('FileAPI.Form.toHtmlData');
this.toHtmlData(fn);
Expand All @@ -35,6 +35,10 @@
api.log('FileAPI.Form.toMultipartData');
this.toMultipartData(fn);
}
else if( api.support.chunked && options.chunkSize > 0 ){
api.log('FileAPI.Form.toMultipartData');
this.toPlainData(fn);
}
else {
api.log('FileAPI.Form.toFormData');
this.toFormData(fn);
Expand Down Expand Up @@ -74,6 +78,19 @@
});
},

toPlainData: function (fn){
this._to({}, fn, function (file, data, queue){
if( file.file ){
data.type = file.file;
}
data.name = file.blob.name;
data.file = file.blob;
data.size = file.blob.size;
data.start = 0;
data.end = 0;
data.retry = 0;
});
},

toFormData: function (fn){
this._to(new FormData, fn, function (file, data, queue){
Expand Down
136 changes: 103 additions & 33 deletions lib/FileAPI.XHR.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
// Start uploading
options.upload(options, _this);
_this._send.call(_this, options, data);
});
}, options);
},

_send: function (options, data){
Expand All @@ -77,6 +77,7 @@
url += (~url.indexOf('?') ? '&' : '?') + api.uid();

if( data.nodeName ){
// legacy
options.upload(options, _this);

xhr = document.createElement('div');
Expand Down Expand Up @@ -125,6 +126,7 @@
form = null;
}
else {
// html5
xhr = _this.xhr = api.getXHR();

xhr.open('POST', url, true);
Expand All @@ -138,46 +140,114 @@
xhr.setRequestHeader(key, val);
});

if( xhr.upload ){
// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29
xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){
options.progress(evt, _this, options);
}, 100), false);
}

xhr.onreadystatechange = function (){
_this.status = xhr.status;
_this.statusText = xhr.statusText;
_this.readyState = xhr.readyState;

if (api.support.chunked && options.chunkSize > 0) {
// resumable upload
if( xhr.upload ){
// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29
xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){
var e = api.extend({}, evt, {
loaded : data.start + evt.loaded,
totalSize : data.size,
total : data.size});
options.progress(e, _this, options);
}, 100), false);
}

if( xhr.readyState == 4 ){
for( var k in { '': 1, XML: 1, Text: 1, Body: 1 } ){
_this['response'+k] = xhr['response'+k];
xhr.onreadystatechange = function (){
_this.status = xhr.status;
_this.statusText = xhr.statusText;
_this.readyState = xhr.readyState;

if( xhr.readyState == 4 ){
for( var k in { '': 1, XML: 1, Text: 1, Body: 1 } ){
_this['response'+k] = xhr['response'+k];
}
xhr.onreadystatechange = null;

if (xhr.status - 201 > 0) {
// some kind of error
if (++data.retry <= options.chunkUploadRetry && (500 == xhr.status || 416 == xhr.status)) {
// let's try again the same chunk
// only applicable for recoverable error codes 500 && 416
data.end = data.start
_this._send(options, data);
} else {
// no mo retries
_this.end(xhr.status);
}
} else {
// success
data.retry = 0;

if (data.end == data.size - 1) {
// finished
_this.end(xhr.status);
} else {
// next chunk
_this._send(options, data);
}
}
xhr = null;
}
xhr.onreadystatechange = null;
_this.end(xhr.status);
xhr = null;
};

data.start = data.end;
data.end = Math.min(data.end + options.chunkSize, data.size ) - 1;

var slice;
(slice = 'slice') in data.file || (slice = 'mozSlice') in data.file || (slice = 'webkitSlice') in data.file;

xhr.setRequestHeader("Content-Range", "bytes " + data.start + "-" + data.end + "/" + data.size);
xhr.setRequestHeader("Content-Disposition", 'attachment; filename=' + data.name);

slice = data.file[slice](data.start, data.end + 1);

xhr.send(slice);
slice = null;
} else {
// single piece upload
if( xhr.upload ){
// https://github.com/blueimp/jQuery-File-Upload/wiki/Fixing-Safari-hanging-on-very-high-speed-connections-%281Gbps%29
xhr.upload.addEventListener('progress', api.throttle(function (/**Event*/evt){
options.progress(evt, _this, options);
}, 100), false);
}
};

xhr.onreadystatechange = function (){
_this.status = xhr.status;
_this.statusText = xhr.statusText;
_this.readyState = xhr.readyState;

if( xhr.readyState == 4 ){
for( var k in { '': 1, XML: 1, Text: 1, Body: 1 } ){
_this['response'+k] = xhr['response'+k];
}
xhr.onreadystatechange = null;
_this.end(xhr.status);
xhr = null;
}
};

if( api.isArray(data) ){
// multipart
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando);
data = data.join('') +'--_'+ api.expando +'--';
if( api.isArray(data) ){
// multipart
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+api.expando);
data = data.join('') +'--_'+ api.expando +'--';

/** @namespace xhr.sendAsBinary https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */
if( xhr.sendAsBinary ){
xhr.sendAsBinary(data);
}
else {
var bytes = Array.prototype.map.call(data, function(c){ return c.charCodeAt(0) & 0xff; });
xhr.send(new Uint8Array(bytes).buffer);
/** @namespace xhr.sendAsBinary https://developer.mozilla.org/ru/XMLHttpRequest#Sending_binary_content */
if( xhr.sendAsBinary ){
xhr.sendAsBinary(data);
}
else {
var bytes = Array.prototype.map.call(data, function(c){ return c.charCodeAt(0) & 0xff; });
xhr.send(new Uint8Array(bytes).buffer);

}
} else {
// FormData
xhr.send(data);
}
}
else {
xhr.send(data);
}
}
}
};
Expand Down
28 changes: 21 additions & 7 deletions lib/FileAPI.core.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
&& !(/safari\//.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25

cors = html5 && ('withCredentials' in (new XMLHttpRequest)),

chunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice||Blob.prototype.mozSlice||Blob.prototype.slice),

document = window.document,

Expand All @@ -35,8 +37,16 @@
_rinput = /input/i,
_rdata = /^data:[^,]+,/,

_KB = 1024,
_pow = Math.pow,
_round = Math.round,
_num = Number,
_from = function (sz) {
return _round(sz * this);
},
_KB = new _num(1024),
_MB = new _num(_pow(_KB, 2)),
_GB = new _num(_pow(_KB, 3)),
_TB = new _num(_pow(_KB, 4)),

_elEvents = {}, // element event listeners
_infoReader = [], // list of file info processors
Expand All @@ -58,11 +68,14 @@

flashUrl: 0, // @default: './FileAPI.flash.swf'
flashImageUrl: 0, // @default: './FileAPI.flash.image.swf'

chunkSize : 0,
chunkUploadRetry : 0,

KB: _KB,
MB: _pow(_KB, 2),
GB: _pow(_KB, 3),
TB: _pow(_KB, 4),
KB: (_KB.from = _from, _KB),
MB: (_MB.from = _from, _MB),
GB: (_GB.from = _from, _GB),
TB: (_TB.from = _from, _TB),

expando: 'fileapi' + (new Date).getTime(),

Expand Down Expand Up @@ -103,6 +116,7 @@
dnd: cors && ('ondrop' in document.createElement('div')),
cors: cors,
html5: html5,
chunked: chunked,
dataURI: true
},

Expand Down Expand Up @@ -712,9 +726,10 @@
, filecomplete: api.F
, progress: api.F
, complete: api.F
, chunkSize: api.chunkSize
, chunkUpoloadRetry: api.chunkUploadRetry
}, options);


if( options.imageAutoOrientation && !options.imageTransform ){
options.imageTransform = { rotate: 'auto' };
}
Expand Down Expand Up @@ -747,7 +762,6 @@

// emit "beforeupload" event
options.beforeupload(proxyXHR, options);

// Upload by file
(function _nextFile(){
var
Expand Down

0 comments on commit cc4c963

Please sign in to comment.