Browse Source

Merge 5cfa35f565 into e11ee26581

pull/832/merge
Jacky Jiang 3 years ago committed by GitHub
parent
commit
4e5a955501
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 58
      papaparse.js

58
papaparse.js

@ -603,6 +603,22 @@ License: MIT
ChunkStreamer.call(this, config); ChunkStreamer.call(this, config);
var xhr; var xhr;
// Will update `totalContentSize` with possible total size info from Content-Range response header
// Its value will be -1 to indicate the total size info can't be retrieve from Content-Range response header (or not available)
var totalContentSize = -1;
// the `this._config.chunkSize` could be large than total size of the file
// which lead to server response 416 (Range Not Satisfiable error) on the first chunk / range request
// If this happened on the first, we should only retry request content without range header once
var shouldDisableChunk = false;
// indicate we are processing the first chunk
// if http 416 error is captured, we will disable chunk and retry the request
var isFirstChunk = true;
// indicate we have retried the request without range header (or without end range if it's not the first chunk)
// we can check this field to make sure that we only ever retry once
var hasRetriedRequestFor416 = false;
if (IS_WORKER) if (IS_WORKER)
{ {
@ -659,9 +675,14 @@ License: MIT
} }
} }
if (this._config.chunkSize) if (this._config.chunkSize && !shouldDisableChunk)
{ {
var end = this._start + this._config.chunkSize - 1; // minus one because byte range is inclusive var end = this._start + this._config.chunkSize - 1; // minus one because byte range is inclusive
if(totalContentSize > 1 && end > totalContentSize - 1) {
// if valid totalContentSize (retrieved from content-range response header) is available
// and end is beyond totalContentSize, replace end with totalContentSize - 1 (as range is inclusive)
end = totalContentSize - 1;
}
xhr.setRequestHeader('Range', 'bytes=' + this._start + '-' + end); xhr.setRequestHeader('Range', 'bytes=' + this._start + '-' + end);
} }
@ -681,14 +702,32 @@ License: MIT
if (xhr.readyState !== 4) if (xhr.readyState !== 4)
return; return;
if (xhr.status === 416 && isFirstChunk && !hasRetriedRequestFor416) {
isFirstChunk = false;
hasRetriedRequestFor416 = true;
shouldDisableChunk = true;
// retry once
this._nextChunk();
return;
}
if (xhr.status < 200 || xhr.status >= 400) if (xhr.status < 200 || xhr.status >= 400)
{ {
this._chunkError(); this._chunkError();
return; return;
} }
// Use chunckSize as it may be a diference on reponse lentgh due to characters with more than 1 byte var size = getFileSize(xhr);
this._start += this._config.chunkSize ? this._config.chunkSize : xhr.responseText.length;
if (size !== -1) {
// we only update totalContentSize when we can get valid content range header
totalContentSize = size;
}
var chunkSize = getChunkSize(xhr);
// Use chunckSize that is retrieved from content-length header if available
this._start += chunkSize !== -1 ? chunkSize : this._config.chunkSize;
this._finished = !this._config.chunkSize || this._start >= getFileSize(xhr); this._finished = !this._config.chunkSize || this._start >= getFileSize(xhr);
this.parseChunk(xhr.responseText); this.parseChunk(xhr.responseText);
}; };
@ -699,13 +738,24 @@ License: MIT
this._sendError(new Error(errorText)); this._sendError(new Error(errorText));
}; };
function getChunkSize(xhr)
{
var contentLength = xhr.getResponseHeader('Content-Length');
if (contentLength === null) { // no content length, return -1 to indicate this
return -1;
}
var length = parseInt(contentLength);
return length > 0 ? length : -1;
}
function getFileSize(xhr) function getFileSize(xhr)
{ {
var contentRange = xhr.getResponseHeader('Content-Range'); var contentRange = xhr.getResponseHeader('Content-Range');
if (contentRange === null) { // no content range, then finish! if (contentRange === null) { // no content range, then finish!
return -1; return -1;
} }
return parseInt(contentRange.substring(contentRange.lastIndexOf('/') + 1)); var size = parseInt(contentRange.substring(contentRange.lastIndexOf('/') + 1));
return size > 0 ? size : -1; // this also exclude the situation that size is NaN
} }
} }
NetworkStreamer.prototype = Object.create(ChunkStreamer.prototype); NetworkStreamer.prototype = Object.create(ChunkStreamer.prototype);

Loading…
Cancel
Save