由于百度智能云没有提供uniapp的sdk,所以只能使用百度的api进行实现。
需要用到小程序大文件上传库。miniprogram-file-uploader | 微信开放文档
npm i miniprogram-file-uploader
在utils文件中创建zoneUpload.js
import Uploader from 'miniprogram-file-uploader'
// 百度云分片上传返回id
var uploadId = '';
export function videoUpload(tempFiles){
return new Promise((resolve,reject)=>{
uni.showLoading({
title:'上传中...',
mask:true
})
// 如果大于10兆使用分片,小于则直接调后端接口上传
if(tempFiles.size > 10 * 1024 * 1024){
zoneUpload(tempFiles).then(res=>{
// 抛出视频地址
resolve(res)
})
}else{
uni.uploadFile({
url: 'https://xxxx/admin/index/uploadVideo',
name: 'file',
header: {},
formData: {},
filePath: tempFiles.tempFilePath || tempFiles.tempVideoPath,
success(res) {
var d = JSON.parse(res.data.replace(/\ufeff/g, '') || '{}');
uni.hideLoading()
resolve(d.data.url)
},
})
}
})
}
// 分片上传
function zoneUpload(tempFilePath){
return new Promise((resolve,reject)=>{
let key ='';
let mydate = new Date();
let myyear = mydate.getFullYear(); //获取完整的年份(4位,1970-????)
let mymonth = mydate.getMonth() + 1; //获取当前月份(0-11,0代表1月)
let mytoday = mydate.getDate(); //获取当前日(1-31)
let myhour = mydate.getHours(); //获取当前小时数(0-23)
let myminute = mydate.getMinutes(); //获取当前分钟数(0-59)
let mysecond = mydate.getSeconds(); //获取当前秒数(0-59)
if (mymonth < 10) mymonth = "0" + mymonth;
if (mytoday < 10) mytoday = "0" + mytoday;
let date = `${myyear}` + `${mymonth}` + `${mytoday}`;
let name =`${myyear}` +`${mymonth}` + `${mytoday}` +`${myhour}` +`${myminute}` +`${mysecond}` +parseInt(Math.random() * 10000);
let arr = '';
if(tempFilePath.tempVideoPath){
arr = tempFilePath.tempVideoPath.split(".");
}else if(tempFilePath.tempFilePath){
arr = tempFilePath.tempFilePath.split(".");
}
// 文件名称
key = "jinan_demo/video/" + date + "/" + name + "." + arr[arr.length - 1];
uni.request({
url: 'https://bj.bcebos.com/v1/' + key + '?uploads',
method: 'POST',
header: {
'content-type': 'text/plain'
},
success: (res) => {
uploadId = res.data.uploadId;
uploadOne(tempFilePath, key).then(res=>{
resolve(res)
})
},
fail: (err) => {
console.log(err,'err')
}
})
})
}
// 上传逻辑
function uploadOne(tempFilePathItem, key) {
return new Promise((resolve,reject)=>{
let obj = tempFilePathItem //图片路径或者视频路径 可以通过chooseMedia的api进行获取
var tempFilePath = obj.tempFilePath || obj.tempVideoPath
var file = {//重点,分片要的参数
ext_file_name: '',
index: 0,
chunkSize: 1024 * 1024 * 1 //分片0.5M 根据自己的分片需求设置一片多大
}
file.ext_file_name = obj.tempFilePath || obj.tempVideoPath
file.index = Math.ceil(obj.size / file.chunkSize) //获取索引
var opt = {
fileName: file.ext_file_name,
totalSize: obj.size,
chunkSize: file.chunkSize,
maxConcurrency: 3 ,
timeout : 20000,
query: { //后端需要的参数
uploadId: uploadId,
},
uploadUrl: `https://bj.bcebos.com/v1/${key}`,
mergeUrl: `https://bj.bcebos.com/v1/${key}?uploadId=${uploadId}`,
tempFilePath: tempFilePath
}
const uploader = new Uploader(opt)
// 成功或失败都会触发
uploader.on('complete', (res) => {
console.log('upload complete', res)
})
uploader.on('retry', (res) => {})
uploader.on('success', (res) => {
console.log('upload success', res)
let uploadId = res.uploadId
uni.request({
url: `https://bj.bcebos.com/v1/${key}?uploadId=${uploadId}`,
method: 'POST',
header:{
"Content-Type":'application/json'
},
data:{
parts:res.parts
},
success: (res) => {
uni.hideLoading()
resolve(res.data.location)
}
})
})
uploader.on('fail', (res) => {
console.log('fail', res)
})
uploader.on('progress', (res) => { //上传进度这里是进度条提供
uni.showLoading({
title: `已上传${res.progress}%`,
mask: true
})
})
uploader.upload()
// this.uploader = uploader
})
}
修改node_modules下的miniprogram-file-uploader/dist/uploader.js 直接覆盖
/**
* miniprogram-uploader 1.0.0
* description: A JavaScript library supports miniprogram to upload large file.
* author: sanfordsun
* Released under the MIT License.
*/
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, basedir, module) {
return module = {
path: basedir,
exports: {},
require: function (path, base) {
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
}
}, fn(module, module.exports), module.exports;
}
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
}
var logger = createCommonjsModule(function (module) {
/*!
* js-logger - http://github.com/jonnyreeves/js-logger
* Jonny Reeves, http://jonnyreeves.co.uk/
* js-logger may be freely distributed under the MIT license.
*/
(function (global) {
// Top level module for the global, static logger instance.
var Logger = { };
// For those that are at home that are keeping score.
Logger.VERSION = "1.6.0";
// Function which handles all incoming log messages.
var logHandler;
// Map of ContextualLogger instances by name; used by Logger.get() to return the same named instance.
var contextualLoggersByNameMap = {};
// Polyfill for ES5's Function.bind.
var bind = function(scope, func) {
return function() {
return func.apply(scope, arguments);
};
};
// Super exciting object merger-matron 9000 adding another 100 bytes to your download.
var merge = function () {
var args = arguments, target = args[0], key, i;
for (i = 1; i < args.length; i++) {
for (key in args[i]) {
if (!(key in target) && args[i].hasOwnProperty(key)) {
target[key] = args[i][key];
}
}
}
return target;
};
// Helper to define a logging level object; helps with optimisation.
var defineLogLevel = function(value, name) {
return { value: value, name: name };
};
// Predefined logging levels.
Logger.TRACE = defineLogLevel(1, 'TRACE');
Logger.DEBUG = defineLogLevel(2, 'DEBUG');
Logger.INFO = defineLogLevel(3, 'INFO');
Logger.TIME = defineLogLevel(4, 'TIME');
Logger.WARN = defineLogLevel(5, 'WARN');
Logger.ERROR = defineLogLevel(8, 'ERROR');
Logger.OFF = defineLogLevel(99, 'OFF');
// Inner class which performs the bulk of the work; ContextualLogger instances can be configured independently
// of each other.
var ContextualLogger = function(defaultContext) {
this.context = defaultContext;
this.setLevel(defaultContext.filterLevel);
this.log = this.info; // Convenience alias.
};
ContextualLogger.prototype = {
// Changes the current logging level for the logging instance.
setLevel: function (newLevel) {
// Ensure the supplied Level object looks valid.
if (newLevel && "value" in newLevel) {
this.context.filterLevel = newLevel;
}
},
// Gets the current logging level for the logging instance
getLevel: function () {
return this.context.filterLevel;
},
// Is the logger configured to output messages at the supplied level?
enabledFor: function (lvl) {
var filterLevel = this.context.filterLevel;
return lvl.value >= filterLevel.value;
},
trace: function () {
this.invoke(Logger.TRACE, arguments);
},
debug: function () {
this.invoke(Logger.DEBUG, arguments);
},
info: function () {
this.invoke(Logger.INFO, arguments);
},
warn: function () {
this.invoke(Logger.WARN, arguments);
},
error: function () {
this.invoke(Logger.ERROR, arguments);
},
time: function (label) {
if (typeof label === 'string' && label.length > 0) {
this.invoke(Logger.TIME, [ label, 'start' ]);
}
},
timeEnd: function (label) {
if (typeof label === 'string' && label.length > 0) {
this.invoke(Logger.TIME, [ label, 'end' ]);
}
},
// Invokes the logger callback if it's not being filtered.
invoke: function (level, msgArgs) {
if (logHandler && this.enabledFor(level)) {
logHandler(msgArgs, merge({ level: level }, this.context));
}
}
};
// Protected instance which all calls to the to level `Logger` module will be routed through.
var globalLogger = new ContextualLogger({ filterLevel: Logger.OFF });
// Configure the global Logger instance.
(function() {
// Shortcut for optimisers.
var L = Logger;
L.enabledFor = bind(globalLogger, globalLogger.enabledFor);
L.trace = bind(globalLogger, globalLogger.trace);
L.debug = bind(globalLogger, globalLogger.debug);
L.time = bind(globalLogger, globalLogger.time);
L.timeEnd = bind(globalLogger, globalLogger.timeEnd);
L.info = bind(globalLogger, globalLogger.info);
L.warn = bind(globalLogger, globalLogger.warn);
L.error = bind(globalLogger, globalLogger.error);
// Don't forget the convenience alias!
L.log = L.info;
}());
// Set the global logging handler. The supplied function should expect two arguments, the first being an arguments
// object with the supplied log messages and the second being a context object which contains a hash of stateful
// parameters which the logging function can consume.
Logger.setHandler = function (func) {
logHandler = func;
};
// Sets the global logging filter level which applies to *all* previously registered, and future Logger instances.
// (note that named loggers (retrieved via `Logger.get`) can be configured independently if required).
Logger.setLevel = function(level) {
// Set the globalLogger's level.
globalLogger.setLevel(level);
// Apply this level to all registered contextual loggers.
for (var key in contextualLoggersByNameMap) {
if (contextualLoggersByNameMap.hasOwnProperty(key)) {
contextualLoggersByNameMap[key].setLevel(level);
}
}
};
// Gets the global logging filter level
Logger.getLevel = function() {
return globalLogger.getLevel();
};
// Retrieve a ContextualLogger instance. Note that named loggers automatically inherit the global logger's level,
// default context and log handler.
Logger.get = function (name) {
// All logger instances are cached so they can be configured ahead of use.
return contextualLoggersByNameMap[name] ||
(contextualLoggersByNameMap[name] = new ContextualLogger(merge({ name: name }, globalLogger.context)));
};
// CreateDefaultHandler returns a handler function which can be passed to `Logger.setHandler()` which will
// write to the window's console object (if present); the optional options object can be used to customise the
// formatter used to format each log message.
Logger.createDefaultHandler = function (options) {
options = options || {};
options.formatter = options.formatter || function defaultMessageFormatter(messages, context) {
// Prepend the logger's name to the log message for easy identification.
if (context.name) {
messages.unshift("[" + context.name + "]");
}
};
// Map of timestamps by timer labels used to track `#time` and `#timeEnd()` invocations in environments
// that don't offer a native console method.
var timerStartTimeByLabelMap = {};
// Support for IE8+ (and other, slightly more sane environments)
var invokeConsoleMethod = function (hdlr, messages) {
Function.prototype.apply.call(hdlr, console, messages);
};
// Check for the presence of a logger.
if (typeof console === "undefined") {
return function () { /* no console */ };
}
return function(messages, context) {
// Convert arguments object to Array.
messages = Array.prototype.slice.call(messages);
var hdlr = console.log;
var timerLabel;
if (context.level === Logger.TIME) {
timerLabel = (context.name ? '[' + context.name + '] ' : '') + messages[0];
if (messages[1] === 'start') {
if (console.time) {
console.time(timerLabel);
}
else {
timerStartTimeByLabelMap[timerLabel] = new Date().getTime();
}
}
else {
if (console.timeEnd) {
console.timeEnd(timerLabel);
}
else {
invokeConsoleMethod(hdlr, [ timerLabel + ': ' +
(new Date().getTime() - timerStartTimeByLabelMap[timerLabel]) + 'ms' ]);
}
}
}
else {
// Delegate through to custom warn/error loggers if present on the console.
if (context.level === Logger.WARN && console.warn) {
hdlr = console.warn;
} else if (context.level === Logger.ERROR && console.error) {
hdlr = console.error;
} else if (context.level === Logger.INFO && console.info) {
hdlr = console.info;
} else if (context.level === Logger.DEBUG && console.debug) {
hdlr = console.debug;
} else if (context.level === Logger.TRACE && console.trace) {
hdlr = console.trace;
}
options.formatter(messages, context);
invokeConsoleMethod(hdlr, messages);
}
};
};
// Configure and example a Default implementation which writes to the `window.console` (if present). The
// `options` hash can be used to configure the default logLevel and provide a custom message formatter.
Logger.useDefaults = function(options) {
Logger.setLevel(options && options.defaultLevel || Logger.DEBUG);
Logger.setHandler(Logger.createDefaultHandler(options));
};
// Export to popular environments boilerplate.
if ( module.exports) {
module.exports = Logger;
}
else {
Logger._prevLogger = global.Logger;
Logger.noConflict = function () {
global.Logger = Logger._prevLogger;
return Logger;
};
global.Logger = Logger;
}
}(commonjsGlobal));
});
var sparkMd5 = createCommonjsModule(function (module, exports) {
(function (factory) {
{
// Node/CommonJS
module.exports = factory();
}
}(function (undefined$1) {
/*
* Fastest md5 implementation around (JKM md5).
* Credits: Joseph Myers
*
* @see http://www.myersdaily.org/joseph/javascript/md5-text.html
* @see http://jsperf.com/md5-shootout/7
*/
/* this function is much faster,
so if possible we use it. Some IEs
are the only ones I know of that
need the idiotic second function,
generated by an if clause. */
var hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
function md5cycle(x, k) {
var a = x[0],
b = x[1],
c = x[2],
d = x[3];
a += (b & c | ~b & d) + k[0] - 680876936 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[1] - 389564586 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[2] + 606105819 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & c | ~b & d) + k[4] - 176418897 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[7] - 45705983 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[10] - 42063 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[13] - 40341101 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & d | c & ~d) + k[1] - 165796510 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[11] + 643717713 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[0] - 373897302 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b & d | c & ~d) + k[5] - 701558691 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[10] + 38016083 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[15] - 660478335 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[4] - 405537848 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b & d | c & ~d) + k[9] + 568446438 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[3] - 187363961 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[2] - 51403784 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b ^ c ^ d) + k[5] - 378558 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[14] - 35309556 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[7] - 155497632 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (b ^ c ^ d) + k[13] + 681279174 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[0] - 358537222 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[3] - 722521979 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[6] + 76029189 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (b ^ c ^ d) + k[9] - 640364487 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[12] - 421815835 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[15] + 530742520 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[2] - 995338651 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
b = (b << 21 |b >>> 11) + c | 0;
a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
b = (b << 21 |b >>> 11) + c | 0;
a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
b = (b << 21 |b >>> 11) + c | 0;
a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
b = (b << 21 | b >>> 11) + c | 0;
x[0] = a + x[0] | 0;
x[1] = b + x[1] | 0;
x[2] = c + x[2] | 0;
x[3] = d + x[3] | 0;
}
function md5blk(s) {
var md5blks = [],
i; /* Andy King said do it this way. */
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
}
return md5blks;
}
function md5blk_array(a) {
var md5blks = [],
i; /* Andy King said do it this way. */
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
}
return md5blks;
}
function md51(s) {
var n = s.length,
state = [1732584193, -271733879, -1732584194, 271733878],
i,
length,
tail,
tmp,
lo,
hi;
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk(s.substring(i - 64, i)));
}
s = s.substring(i - 64);
length = s.length;
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
}
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
// Beware that the final length might not fit in 32 bits so we take care of that
tmp = n * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(state, tail);
return state;
}
function md51_array(a) {
var n = a.length,
state = [1732584193, -271733879, -1732584194, 271733878],
i,
length,
tail,
tmp,
lo,
hi;
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
}
// Not sure if it is a bug, however IE10 will always produce a sub array of length 1
// containing the last element of the parent array if the sub array specified starts
// beyond the length of the parent array - weird.
// https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
length = a.length;
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= a[i] << ((i % 4) << 3);
}
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
// Beware that the final length might not fit in 32 bits so we take care of that
tmp = n * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(state, tail);
return state;
}
function rhex(n) {
var s = '',
j;
for (j = 0; j < 4; j += 1) {
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
}
return s;
}
function hex(x) {
var i;
for (i = 0; i < x.length; i += 1) {
x[i] = rhex(x[i]);
}
return x.join('');
}
// In some cases the fast add32 function cannot be used..
if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') ;
// ---------------------------------------------------
/**
* ArrayBuffer slice polyfill.
*
* @see https://github.com/ttaubert/node-arraybuffer-slice
*/
if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
(function () {
function clamp(val, length) {
val = (val | 0) || 0;
if (val < 0) {
return Math.max(val + length, 0);
}
return Math.min(val, length);
}
ArrayBuffer.prototype.slice = function (from, to) {
var length = this.byteLength,
begin = clamp(from, length),
end = length,
num,
target,
targetArray,
sourceArray;
if (to !== undefined$1) {
end = clamp(to, length);
}
if (begin > end) {
return new ArrayBuffer(0);
}
num = end - begin;
target = new ArrayBuffer(num);
targetArray = new Uint8Array(target);
sourceArray = new Uint8Array(this, begin, num);
targetArray.set(sourceArray);
return target;
};
})();
}
// ---------------------------------------------------
/**
* Helpers.
*/
function toUtf8(str) {
if (/[\u0080-\uFFFF]/.test(str)) {
str = unescape(encodeURIComponent(str));
}
return str;
}
function utf8Str2ArrayBuffer(str, returnUInt8Array) {
var length = str.length,
buff = new ArrayBuffer(length),
arr = new Uint8Array(buff),
i;
for (i = 0; i < length; i += 1) {
arr[i] = str.charCodeAt(i);
}
return returnUInt8Array ? arr : buff;
}
function arrayBuffer2Utf8Str(buff) {
return String.fromCharCode.apply(null, new Uint8Array(buff));
}
function concatenateArrayBuffers(first, second, returnUInt8Array) {
var result = new Uint8Array(first.byteLength + second.byteLength);
result.set(new Uint8Array(first));
result.set(new Uint8Array(second), first.byteLength);
return returnUInt8Array ? result : result.buffer;
}
function hexToBinaryString(hex) {
var bytes = [],
length = hex.length,
x;
for (x = 0; x < length - 1; x += 2) {
bytes.push(parseInt(hex.substr(x, 2), 16));
}
return String.fromCharCode.apply(String, bytes);
}
// ---------------------------------------------------
/**
* SparkMD5 OOP implementation.
*
* Use this class to perform an incremental md5, otherwise use the
* static methods instead.
*/
function SparkMD5() {
// call reset to init the instance
this.reset();
}
/**
* Appends a string.
* A conversion will be applied if an utf8 string is detected.
*
* @param {String} str The string to be appended
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.append = function (str) {
// Converts the string to utf8 bytes if necessary
// Then append as binary
this.appendBinary(toUtf8(str));
return this;
};
/**
* Appends a binary string.
*
* @param {String} contents The binary string to be appended
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.appendBinary = function (contents) {
this._buff += contents;
this._length += contents.length;
var length = this._buff.length,
i;
for (i = 64; i <= length; i += 64) {
md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
}
this._buff = this._buff.substring(i - 64);
return this;
};
/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
*
* @param {Boolean} raw True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.prototype.end = function (raw) {
var buff = this._buff,
length = buff.length,
i,
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
ret;
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
}
this._finish(tail, length);
ret = hex(this._hash);
if (raw) {
ret = hexToBinaryString(ret);
}
this.reset();
return ret;
};
/**
* Resets the internal state of the computation.
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.reset = function () {
this._buff = '';
this._length = 0;
this._hash = [1732584193, -271733879, -1732584194, 271733878];
return this;
};
/**
* Gets the internal state of the computation.
*
* @return {Object} The state
*/
SparkMD5.prototype.getState = function () {
return {
buff: this._buff,
length: this._length,
hash: this._hash.slice()
};
};
/**
* Gets the internal state of the computation.
*
* @param {Object} state The state
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.setState = function (state) {
this._buff = state.buff;
this._length = state.length;
this._hash = state.hash;
return this;
};
/**
* Releases memory used by the incremental buffer and other additional
* resources. If you plan to use the instance again, use reset instead.
*/
SparkMD5.prototype.destroy = function () {
delete this._hash;
delete this._buff;
delete this._length;
};
/**
* Finish the final calculation based on the tail.
*
* @param {Array} tail The tail (will be modified)
* @param {Number} length The length of the remaining buffer
*/
SparkMD5.prototype._finish = function (tail, length) {
var i = length,
tmp,
lo,
hi;
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(this._hash, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
// Do the final computation based on the tail and length
// Beware that the final length may not fit in 32 bits so we take care of that
tmp = this._length * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(this._hash, tail);
};
/**
* Performs the md5 hash on a string.
* A conversion will be applied if utf8 string is detected.
*
* @param {String} str The string
* @param {Boolean} [raw] True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.hash = function (str, raw) {
// Converts the string to utf8 bytes if necessary
// Then compute it using the binary function
return SparkMD5.hashBinary(toUtf8(str), raw);
};
/**
* Performs the md5 hash on a binary string.
*
* @param {String} content The binary string
* @param {Boolean} [raw] True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.hashBinary = function (content, raw) {
var hash = md51(content),
ret = hex(hash);
return raw ? hexToBinaryString(ret) : ret;
};
// ---------------------------------------------------
/**
* SparkMD5 OOP implementation for array buffers.
*
* Use this class to perform an incremental md5 ONLY for array buffers.
*/
SparkMD5.ArrayBuffer = function () {
// call reset to init the instance
this.reset();
};
/**
* Appends an array buffer.
*
* @param {ArrayBuffer} arr The array to be appended
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.append = function (arr) {
var buff = concatenateArrayBuffers(this._buff.buffer, arr, true),
length = buff.length,
i;
this._length += arr.byteLength;
for (i = 64; i <= length; i += 64) {
md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
}
this._buff = (i - 64) < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
return this;
};
/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
*
* @param {Boolean} raw True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.ArrayBuffer.prototype.end = function (raw) {
var buff = this._buff,
length = buff.length,
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
i,
ret;
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff[i] << ((i % 4) << 3);
}
this._finish(tail, length);
ret = hex(this._hash);
if (raw) {
ret = hexToBinaryString(ret);
}
this.reset();
return ret;
};
/**
* Resets the internal state of the computation.
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.reset = function () {
this._buff = new Uint8Array(0);
this._length = 0;
this._hash = [1732584193, -271733879, -1732584194, 271733878];
return this;
};
/**
* Gets the internal state of the computation.
*
* @return {Object} The state
*/
SparkMD5.ArrayBuffer.prototype.getState = function () {
var state = SparkMD5.prototype.getState.call(this);
// Convert buffer to a string
state.buff = arrayBuffer2Utf8Str(state.buff);
return state;
};
/**
* Gets the internal state of the computation.
*
* @param {Object} state The state
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.setState = function (state) {
// Convert string to buffer
state.buff = utf8Str2ArrayBuffer(state.buff, true);
return SparkMD5.prototype.setState.call(this, state);
};
SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
/**
* Performs the md5 hash on an array buffer.
*
* @param {ArrayBuffer} arr The array buffer
* @param {Boolean} [raw] True to get the raw string, false to get the hex one
*
* @return {String} The result
*/
SparkMD5.ArrayBuffer.hash = function (arr, raw) {
var hash = md51_array(new Uint8Array(arr)),
ret = hex(hash);
return raw ? hexToBinaryString(ret) : ret;
};
return SparkMD5;
}));
});
var config = {
tempFilePath: '',
totalSize: 0,
fileName: '',
verifyUrl: '',
uploadUrl: '',
mergeUrl: '',
maxConcurrency: 5,
generateIdentifier: null,
chunkSize: 5 * 1024 * 1024,
maxMemory: 100 * 1024 * 1024,
query: '',
header: {},
testChunks: false,
chunkRetryInterval: 0,
maxChunkRetries: 0,
timeout: 10000,
successStatus: [200, 201, 202],
failStatus: [404, 415, 500, 501],
verbose: false
};
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (typeof this.events[event] !== 'object') {
this.events[event] = [];
}
this.events[event].push(listener);
return () => this.off(event, listener)
}
off(event, listener) {
if (typeof this.events[event] === 'object') {
const idx = this.events[event].indexOf(listener);
if (idx > -1) {
this.events[event].splice(idx, 1);
}
}
}
emit(event, ...args) {
if (typeof this.events[event] === 'object') {
this.events[event].forEach(listener => listener.apply(this, args));
}
}
once(event, listener) {
const remove = this.on(event, (...args) => {
remove();
listener.apply(this, args);
});
}
}
const isFunction = x => typeof x === 'function';
function promisify(func) {
if (!isFunction(func)) return func
return (args = {}) => new Promise((resolve, reject) => {
func(
Object.assign(args, {
success: resolve,
fail: reject
})
);
})
}
function addParams(url = '', params = {}) {
const parts = url.split('?');
const query = Object.keys(params).map(key => `${key}=${params[key]}`).join('&');
return query ? `${parts[0]}?${query}` : parts[0]
}
const awaitWrap = (promise) => promise
.then(data => [null, data])
.catch(err => [err, null]);
const compareVersion = (v1, v2) => {
v1 = v1.split('.');
v2 = v2.split('.');
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10);
const num2 = parseInt(v2[i], 10);
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
};
logger.useDefaults({
defaultLevel: logger.OFF,
formatter(messages) {
const now = new Date();
const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
messages.unshift(time);
messages.unshift('[Uploader]');
}
});
const fileManager = wx.getFileSystemManager();
const readFileAsync = promisify(fileManager.readFile);
const miniProgram = wx.getAccountInfoSync();
const systemInfo = wx.getSystemInfoSync();
const appId = miniProgram.appId;
const MB = 1024 * 1024;
class Uploader {
constructor(option = {}) {
if (option.verbose) logger.setLevel(logger.INFO);
logger.debug('construct option ', option);
this.config = Object.assign(config, option);
this.emitter = new EventEmitter();
this.totalSize = this.config.totalSize;
this.chunkSize = this.config.chunkSize;
this.tempFilePath = this.config.tempFilePath;
this.totalChunks = Math.ceil(this.totalSize / this.chunkSize);
this.maxLoadChunks = Math.floor(this.config.maxMemory / this.chunkSize);
this._event();
}
static isSupport() {
const version = systemInfo.SDKVersion;
return compareVersion(version, '2.10.0') >= 0
}
async upload() {
this._reset();
logger.info('start generateIdentifier');
// step1: 计算 identifier
try {
logger.time('[Uploader] generateIdentifier');
if (this.config.testChunks) {
this.identifier = await this.computeMD5();
} else {
this.identifier = this.generateIdentifier();
}
logger.timeEnd('[Uploader] generateIdentifier');
logger.debug('generateIdentifier ', this.identifier);
} catch (error) {
this.handleFail({
errCode: 10002,
errMsg: error.message
});
return
}
logger.info('generateIdentifier end');
// step2: 获取已上传分片
if (this.config.testChunks && this.config.verifyUrl) {
logger.info('start verify uploaded chunks');
logger.time('[Uploader] verifyRequest');
const [verifyErr, verifyResp] = await awaitWrap(this.verifyRequest());
logger.timeEnd('[Uploader] verifyRequest');
logger.debug('verifyRequest', verifyErr, verifyResp);
if (verifyErr) {
this.handleFail({
errCode: 20001,
errMsg: verifyErr.errMsg
});
return
}
const {
needUpload,
uploadedChunks,
} = verifyResp.data;
logger.info('verify uploaded chunks end');
// 秒传逻辑
// 找不到合成的文件
if (!needUpload) {
this.progress = 100;
this.timeRemaining = 0;
this.dispatchProgress();
this.emit('success', {
errCode: 0,
...verifyResp.data
});
this.emit('complete', {
errCode: 0,
...verifyResp.data
});
return
// 分片齐全,但没有合并
} else if (uploadedChunks.length === this.totalChunks) {
this.progress = 100;
this.timeRemaining = 0;
this.dispatchProgress();
this.emit('uploadDone');
return
} else {
this.chunksIndexNeedRead = this.chunksIndexNeedRead.filter(v => !uploadedChunks.includes(v));
this.chunksIndexNeedSend = this.chunksIndexNeedSend.filter(v => !uploadedChunks.includes(v));
this.uploadedChunks = uploadedChunks.sort();
}
}
this.chunksNeedSend = this.chunksIndexNeedSend.length;
this.sizeNeedSend = this.chunksNeedSend * this.chunkSize;
if (this.chunksIndexNeedSend.includes(this.totalChunks - 1)) {
this.sizeNeedSend -= (this.totalChunks * this.chunkSize - this.totalSize);
}
logger.debug(`
start upload
uploadedChunks: ${this.uploadedChunks},
chunksQueue: ${this.chunksQueue},
chunksIndexNeedRead: ${this.chunksIndexNeedRead},
chunksNeedSend: ${this.chunksIndexNeedSend},
sizeNeedSend: ${this.sizeNeedSend}
`);
logger.info('start upload chunks');
logger.time('[Uploader] uploadChunks');
// step3: 开始上传
this.isUploading = true;
this._upload();
}
_requestAsync(args = {}, callback) {
const {
chunkRetryInterval,
maxChunkRetries,
successStatus,
failStatus
} = this.config;
let retries = maxChunkRetries;
return new Promise((resolve, reject) => {
const doRequest = () => {
const task = wx.request({
...args,
timeout: this.config.timeout,
success: (res) => {
const statusCode = res.statusCode;
// 标示成功的返回码
if (successStatus.includes(statusCode)) {
resolve(res);
// 标示失败的返回码
} else if (failStatus.includes(statusCode)) {
reject(res);
} else if (retries > 0) {
setTimeout(() => {
this.emit('retry', {
statusCode,
url: args.url
});
--retries;
doRequest();
}, chunkRetryInterval);
} else {
reject(res);
}
},
fail: (res) => {
reject(res);
}
});
if (isFunction(callback)) {
callback(task);
}
};
doRequest();
})
}
handleFail(e) {
if (this.isFail) return
logger.error('upload file fail: ', e);
this.isFail = true;
this.cancel();
this.emit('fail', e);
this.emit('complete', e);
}
_event() {
// step4: 发送合并请求
this.on('uploadDone', async () => {
logger.timeEnd('[Uploader] uploadChunks');
logger.info('upload chunks end');
this.isUploading = false;
logger.info('start merge reqeust');
logger.time('[Uploader] mergeRequest');
const [mergeErr, mergeResp] = await awaitWrap(this.mergeRequest());
logger.timeEnd('[Uploader] mergeRequest');
logger.info('merge reqeust end');
logger.debug('mergeRequest', mergeErr, mergeResp);
if (mergeErr) {
this.handleFail({
errCode: 20003,
errrMsg: mergeErr.errMsg
});
return
}
logger.info('upload file success');
this.emit('success', {
errCode: 0,
...mergeResp.data
});
this.emit('complete', {
errCode: 0,
...mergeResp.data
});
});
}
_upload() {
this.startUploadTime = Date.now();
this._uploadedSize = 0;
if (this.chunksQueue.length) {
const maxConcurrency = this.config.maxConcurrency;
for (let i = 0; i < maxConcurrency; i++) {
this.uploadChunk();
}
} else {
this.readFileChunk();
}
}
updateUploadSize(currUploadSize) {
this.uploadedSize += currUploadSize; // 总体上传大小,暂停后累计
this._uploadedSize += currUploadSize; // 上传大小,暂停后清空
const time = Date.now() - this.startUploadTime; // 当前耗时
const averageSpeed = this._uploadedSize / time; // B/ms
const sizeWaitSend = this.sizeNeedSend - this.uploadedSize; // 剩余需要发送的大小
this.timeRemaining = parseInt(sizeWaitSend / averageSpeed, 10); // 剩余时间
this.averageSpeed = parseInt(averageSpeed, 10) * 1000; // 平均速度 B/s
this.progress = parseInt(((this.uploadedSize * 100) / this.sizeNeedSend), 10);
this.dispatchProgress();
}
dispatchProgress() {
this.emit('progress', {
totalSize: this.totalSize,
progress: this.progress,
uploadedSize: this.uploadedSize,
averageSpeed: this.averageSpeed,
timeRemaining: this.timeRemaining
});
}
pause() {
logger.info('** pause **');
this.isUploading = false;
const abortIndex = Object.keys(this.uploadTasks).map(v => v * 1);
abortIndex.forEach(index => {
this.chunksIndexNeedRead.push(index);
this.uploadTasks[index].abort();
});
this.uploadTasks = {};
}
resume() {
logger.info('** resume **');
this.isUploading = true;
this._upload();
}
cancel() {
logger.info('** cancel **');
this.pause();
this._reset();
}
_reset() {
this.chunksIndexNeedRead = Array.from(Array(this.totalChunks).keys());
this.chunksIndexNeedSend = Array.from(Array(this.totalChunks).keys());
this.chunksNeedSend = this.totalChunks;
this.sizeNeedSend = this.totalSize;
this.identifier = '';
this.chunksSend = 0;
this.chunksQueue = [];
this.uploadTasks = {};
this.pUploadList = [];
this.uploadedChunks = [];
this.isUploading = false;
this.isFail = false;
this.progress = 0;
this.uploadedSize = 0;
this.averageSpeed = 0;
this.timeRemaining = Number.POSITIVE_INFINITY;
this.dispatchProgress();
}
readFileChunk() {
const {
tempFilePath,
chunkSize,
maxLoadChunks,
chunksQueue,
chunksIndexNeedRead,
totalSize
} = this;
const chunks = Math.min(chunksIndexNeedRead.length, maxLoadChunks - chunksQueue.length);
// 异步读取
logger.debug(`readFileChunk chunks: ${chunks}, chunksIndexNeedRead`, this.chunksIndexNeedRead);
for (let i = 0; i < chunks; i++) {
const index = chunksIndexNeedRead.shift();
const position = index * chunkSize;
const length = Math.min(totalSize - position, chunkSize);
if (this.isFail) break
readFileAsync({
filePath: tempFilePath,
position,
length
}).then(res => {
const chunk = res.data;
this.chunksQueue.push({
chunk,
length,
index
});
this.uploadChunk();
return null
}).catch(e => {
this.handleFail({
errCode: 10001,
errMsg: e.errMsg
});
});
}
}
uploadChunk() {
// 暂停中
if (!this.isUploading || this.isFail) return
// 没有更多数据了
if (!this.chunksQueue.length) return
// 达到最大并发度
if (Object.keys(this.uploadTasks).length === this.config.maxConcurrency) return
const {
chunk,
index,
length
} = this.chunksQueue.shift();
// 跳过已发送的分块
if (this.uploadedChunks.includes(index)) {
this.uploadChunk();
return
}
const {
uploadUrl,
query,
header
} = this.config;
const identifier = this.identifier;
const url = addParams(uploadUrl, {
...query,
// identifier,
// index,
// chunkSize: length,
// fileName: this.config.fileName,
// totalChunks: this.totalChunks,
// totalSize: this.totalSize,
partNumber: index + 1
});
logger.debug(`uploadChunk index: ${index}, lenght ${length}`);
logger.time(`[Uploader] uploadChunk index-${index}`);
this._requestAsync({
url,
data: chunk,
header: {
...header,
'content-type': 'application/octet-stream'
},
method: 'POST',
}, (task) => {
this.uploadTasks[index] = task;
}).then(() => {
this.chunksSend++;
delete this.uploadTasks[index];
this.updateUploadSize(length);
logger.debug(`uploadChunk success chunksSend: ${this.chunksSend}`);
logger.timeEnd(`[Uploader] uploadChunk index-${index}`);
// 尝试继续加载文件
this.readFileChunk();
// 尝试继续发送下一条
this.uploadChunk();
// 所有分片发送完毕
if (this.chunksSend === this.chunksNeedSend) {
this.emit('uploadDone');
}
return null
}).catch(res => {
if (res.errMsg.includes('request:fail abort')) {
logger.info(`chunk index-${index} will be aborted`);
} else {
this.handleFail({
errCode: 20002,
errMsg: res.errMsg
});
}
});
}
emit(event, data) {
this.emitter.emit(event, data);
}
on(event, listenr) {
this.emitter.on(event, listenr);
}
off(event, listenr) {
this.emitter.off(event, listenr);
}
generateIdentifier() {
let identifier = '';
const generator = this.config.generateIdentifier;
if (isFunction(generator)) {
identifier = generator();
} else {
const uuid = `${appId}-${Date.now()}-${Math.random()}`;
identifier = sparkMd5.hash(uuid);
}
return identifier
}
async computeMD5() {
const {
tempFilePath,
totalSize,
chunkSize
} = this;
// 文件比内存限制小时,保存分片
const isltMaxMemory = totalSize < this.config.maxMemory;
const sliceSize = isltMaxMemory ? chunkSize : 10 * MB;
const sliceNum = Math.ceil(totalSize / sliceSize);
const spark = new sparkMd5.ArrayBuffer();
for (let i = 0; i < sliceNum; i++) {
const position = i * sliceSize;
const length = Math.min(totalSize - position, sliceSize);
// eslint-disable-next-line no-await-in-loop
const [readFileErr, readFileResp] = await awaitWrap(readFileAsync({
filePath: tempFilePath,
position,
length
}));
if (readFileErr) {
spark.destroy();
throw (new Error(readFileErr.errMsg))
}
const chunk = readFileResp.data;
if (isltMaxMemory) {
this.chunksQueue.push({
chunk,
length,
index: i
});
}
spark.append(chunk);
}
this.chunksIndexNeedRead = [];
const identifier = spark.end();
spark.destroy();
return identifier
}
async verifyRequest() {
const {
verifyUrl,
fileName
} = this.config;
const verifyResp = await this._requestAsync({
url: verifyUrl,
data: {
fileName,
identifier: this.identifier
}
});
return verifyResp
}
async mergeRequest() {
const {
mergeUrl,
fileName
} = this.config;
const mergeResp = await this._requestAsync({
url: mergeUrl,
data: {
fileName,
identifier: this.identifier
}
});
return mergeResp
}
}
export default Uploader;
//# sourceMappingURL=uploader.js.map