@rpldy/chunked-sender
Version:
adds chunked upload capabilities on top of the regular XHR uploads
93 lines (92 loc) • 3.41 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _shared = require("@rpldy/shared");
var _simpleState = require("@rpldy/simple-state");
var _sender = _interopRequireDefault(require("@rpldy/sender"));
var _utils = require("../utils");
var _consts = require("../consts");
var _ChunkedSendError = _interopRequireDefault(require("./ChunkedSendError"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const getContentRangeValue = (chunk, data, item) => data && `bytes ${chunk.start}-${chunk.start + data.size - 1}/${item.file.size}`;
const mergeWithUndefined = (0, _shared.getMerge)({
undefinedOverwrites: true
});
const getSkippedResult = () => ({
request: Promise.resolve({
state: _shared.FILE_STATES.FINISHED,
response: "skipping chunk as instructed by CHUNK_START handler",
status: 200
}),
abort: () => true,
senderType: "chunk-skipped-sender"
});
const uploadChunkWithUpdatedData = (chunk, chunkedState, item, onProgress, trigger) => {
const state = chunkedState.getState();
const unwrappedOptions = (0, _simpleState.unwrap)(state.sendOptions);
const sendOptions = {
...unwrappedOptions,
headers: {
...unwrappedOptions.headers,
"Content-Range": getContentRangeValue(chunk, chunk.data, item)
}
};
const chunkItem = (0, _shared.createBatchItem)(chunk.data, chunk.id);
const onChunkProgress = e => {
onProgress(e, [chunk]);
};
const chunkIndex = state.chunks.indexOf(chunk);
return (0, _shared.triggerUpdater)(trigger, _consts.CHUNK_EVENTS.CHUNK_START, {
item: (0, _simpleState.unwrap)(item),
chunk: (0, _shared.pick)(chunk, ["id", "start", "end", "index", "attempt"]),
chunkItem: {
...chunkItem
},
sendOptions,
url: state.url,
chunkIndex,
remainingCount: state.chunks.length,
totalCount: state.chunkCount,
onProgress
}).then(response => {
let result;
const updatedData = typeof response === "boolean" ? response === false ? {
stop: true
} : {} : response || {};
if (updatedData.stop) {
_shared.logger.debugLog(`chunkedSender.sendChunk: received false from CHUNK_START handler - skipping chunk ${chunkIndex}, item ${item.id}`);
result = getSkippedResult();
} else {
result = (0, _sender.default)([chunkItem], updatedData?.url || state.url, mergeWithUndefined({}, sendOptions, updatedData?.sendOptions), onChunkProgress);
}
return result;
});
};
const sendChunk = (chunk, chunkedState, item, onProgress, trigger) => {
if (!chunk.data) {
chunkedState.updateState(() => {
chunk.data = (0, _utils.getChunkDataFromFile)(item.file, chunk.start, chunk.end);
});
}
if (!chunk.data) {
throw new _ChunkedSendError.default("chunk failure - failed to slice");
}
const url = chunkedState.getState().url;
_shared.logger.debugLog(`chunkedSender.sendChunk: about to send chunk ${chunk.id} [${chunk.start}-${chunk.end}] to: ${url || ""}`);
const chunkXhrRequest = uploadChunkWithUpdatedData(chunk, chunkedState, item, onProgress, trigger);
return {
request: chunkXhrRequest.then(({
request
}) => request),
abort: () => {
chunkXhrRequest.then(({
abort
}) => abort());
return true;
},
senderType: "chunk-passthrough-sender"
};
};
var _default = exports.default = sendChunk;