Commit d0a1655b authored by 吴永生#A02208's avatar 吴永生#A02208

feat: 文件传输开发

parent 644ad72e
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 16:50:40
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-13 21:09:24
* @FilePath: /bkunyun/src/hooks/useGlobalStore.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { useContext } from 'react';
import { MobXProviderContext } from 'mobx-react';
import { Stores } from '@/store';
export default function useGlobalStore<T extends keyof Stores>(storeName: T) {
const context = useContext(MobXProviderContext) as Stores;
return context[storeName];
}
\ No newline at end of file
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 17:00:19
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-14 11:06:13
* @FilePath: /bkunyun/src/store/modules/upload.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { makeAutoObservable } from "mobx";
interface IUploadInfo {
id: string,
open: boolean,
list: any,
isPermanence: boolean,
}
/** 存储地图派单websocket推送数据状态的store */
class FileList {
constructor() {
makeAutoObservable(this);
}
/** 文件上传列表 */
fileList: IUploadInfo[] = [];
setFileList (val: IUploadInfo[]) {
this.fileList = val
}
/** 设置文件上传信息 */
setUploadInfo(id: string, val: IUploadInfo) {
const newFileList = this.fileList?.map((item)=>{
if(item.id === id){
return val
} return item
})
this.fileList = newFileList
}
setUploadInfoOpen(id: string, val: boolean) {
const newFileList = this.fileList?.map((item)=>{
if(item.id === id){
return {...item,open: val};
}
return item;
})
this.fileList = newFileList
}
setUploadInfoList(id: string, val: any) {
const newFileList = this.fileList?.map((item)=>{
if(item.id === id){
return {...item, list: val}
} return item
})
this.fileList = newFileList
}
setUploadInfoIsPermanence(id: string, val: boolean) {
const newFileList = this.fileList?.map((item)=>{
if(item.id === id){
return {...item, isPermanence: val}
} return item
})
this.fileList = newFileList
}
}
export default new FileList();
import React from "react";
import * as tus from "tus-js-client";
import {
verifyLettersNumbersCertainChars4,
verifyLettersNumbersCertainChars5,
} from "../helper";
const UseTusUpload = (props) => {
const { fileList: uploadInfoStore } = props;
console.log(uploadInfoStore, 222);
const uploadInfoList = uploadInfoStore?.uploadInfo?.list || [];
const uploadInfoIsPermanence =
uploadInfoStore?.uploadInfo?.isPermanence || [];
const uploadInfoOpen = uploadInfoStore?.uploadInfo?.open || [];
const uploadFile = (id, file, url, filepath, callBack) => {
for (let i in localStorage) {
if (i.indexOf("tus::tus-br") > -1) {
localStorage.removeItem(i);
}
}
uploadInfoStore?.setUploadInfoIsPermanence(id, false);
if (!verifyLettersNumbersCertainChars4(file.name)) {
let json1 = uploadInfoStore?.uploadInfo?.list.concat({
name: file.name,
bytesUploaded: 0,
bytesTotal: 0,
percentage: 0,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
bytesUploaded2: 0,
fileIsCn: true,
statusMsg: "上传失败",
upload: null,
id: new Date().getTime(),
statusMsgDetail:
"上传失败,文件或文件夹的命名长度不超过127字节,不支持特殊符号、空格。",
});
uploadInfoStore?.setUploadInfo(id, {
open: true,
list: json1,
isPermanence: false,
});
return;
}
// Create a new tus upload
let timeId = new Date().getTime();
let headers = {
username: "",
token: "",
filetoken: "",
share: false,
};
let upload = new tus.Upload(file, {
endpoint: url,
parallelUploads: 1,
chunkSize: 5242880,
metadata: {
filepath: filepath,
},
retryDelays: [0, 3000, 5000, 10000, 20000],
headers: headers,
onError: function (error) {
console.log("Failed because: " + error);
},
onProgress: function (bytesUploaded, bytesTotal, a) {
var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
let fliterJson = uploadInfoList?.filter((item) => item.id === timeId);
let json = [];
if (fliterJson.length === 0) {
json = uploadInfoList.concat({
name: upload.file.name,
bytesUploaded: bytesUploaded,
bytesTotal: bytesTotal,
percentage: percentage,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
bytesUploaded2: bytesUploaded,
id: timeId,
statusMsg: "正在上传",
upload,
dir: "/home/cloudam/",
});
uploadInfoStore?.setUploadInfo(id, {
open: true,
list: json,
isPermanence: uploadInfoStore?.uploadInfo?.isPermanence,
});
} else {
let a = uploadInfoList;
let time = new Date().getTime();
a.map((element) => {
if (element.id === timeId) {
element["bytesUploaded"] = bytesUploaded;
element["bytesTotal"] = bytesTotal;
element["percentage"] = percentage;
element["bytesUploaded2"] =
parseInt((parseInt(time) - parseInt(element.endTime)) / 1000) >=
2
? bytesUploaded
: element["bytesUploaded2"];
element["endTime"] =
parseInt((parseInt(time) - parseInt(element.endTime)) / 1000) >=
2
? time
: element["endTime"];
}
});
uploadInfoStore?.setUploadInfo(id, {
open: true,
list: a.concat([]),
isPermanence: uploadInfoIsPermanence,
});
}
},
onSuccess: function () {
let fliterJson = uploadInfoList.filter((item) => item.id === timeId);
if (fliterJson.length === 0 && upload.file["size"] === 0) {
let json = [];
json = uploadInfoList.concat({
name: upload.file.name,
bytesUploaded: 0,
bytesTotal: 0,
id: timeId,
percentage: 100,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
bytesUploaded2: 0,
statusMsg: "上传成功",
upload,
});
uploadInfoStore?.setUploadInfo(id, {
open: true,
list: json,
isPermanence: uploadInfoIsPermanence,
});
} else {
uploadInfoList.map((item) => {
if (item.id === timeId) {
item["statusMsg"] = "上传成功";
}
});
uploadInfoStore?.setUploadInfo(id, {
open: true,
list: uploadInfoList,
isPermanence: uploadInfoIsPermanence,
});
}
callBack && callBack(upload, filepath);
},
});
// Start the upload
upload.start();
};
const uploadFileCallBack = (file, url, filepath, callBack) => {
if (!verifyLettersNumbersCertainChars4(file.name)) {
let json1 = uploadInfoList.concat({
name: file.name,
bytesUploaded: 0,
bytesTotal: 0,
percentage: 0,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
bytesUploaded2: 0,
fileIsCn: true,
id: new Date().getTime,
statusMsg: "上传失败",
upload: null,
statusMsgDetail:
"上传失败,文件或文件夹的命名长度不超过127字节,不支持特殊符号、空格。",
});
uploadInfoStore?.setUploadInfo({
open: true,
list: json1,
isPermanence: false,
});
return;
}
for (let i in localStorage) {
if (i.indexOf("tus::tus-br") > -1) {
localStorage.removeItem(i);
}
}
uploadInfoStore?.setUploadInfoIsPermanence(false);
// Create a new tus upload
let timeId = new Date().getTime();
let headers = {
username: "",
token: "",
filetoken: "",
share: false,
};
let upload = new tus.Upload(file, {
endpoint: url,
parallelUploads: 1,
chunkSize: 5242880,
metadata: {
filepath: filepath,
},
retryDelays: [0, 3000, 5000, 10000, 20000],
headers: headers,
onError: function (error) {
console.log("Failed because: " + error);
},
onProgress: function (bytesUploaded, bytesTotal, a) {
var percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
let fliterJson = uploadInfoList.filter((item) => item.id === timeId);
let json = [];
if (fliterJson.length === 0) {
json = uploadInfoList.concat({
name: upload.file.name,
bytesUploaded: bytesUploaded,
bytesTotal: bytesTotal,
percentage: percentage,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
bytesUploaded2: bytesUploaded,
id: timeId,
statusMsg: "正在上传",
upload,
dir: "/home/cloudam/",
});
uploadInfoStore?.setUploadInfo({
open: true,
list: json,
isPermanence: uploadInfoIsPermanence,
});
} else {
let a = uploadInfoList;
let time = new Date().getTime();
a.map((element) => {
if (element.id === timeId) {
element["bytesUploaded"] = bytesUploaded;
element["bytesTotal"] = bytesTotal;
element["percentage"] = percentage;
element["bytesUploaded2"] =
parseInt((parseInt(time) - parseInt(element.endTime)) / 1000) >=
2
? bytesUploaded
: element["bytesUploaded2"];
element["endTime"] =
parseInt((parseInt(time) - parseInt(element.endTime)) / 1000) >=
2
? time
: element["endTime"];
}
});
uploadInfoStore?.setUploadInfo({
open: true,
list: a.concat([]),
isPermanence: uploadInfoIsPermanence,
});
}
},
onSuccess: function () {
let fliterJson = uploadInfoList.filter((item) => item.id === timeId);
if (fliterJson.length === 0 && upload.file["size"] === 0) {
let json = [];
json = uploadInfoList.concat({
name: upload.file.name,
bytesUploaded: 0,
bytesTotal: 0,
id: timeId,
percentage: 100,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
bytesUploaded2: 0,
statusMsg: "上传成功",
upload,
});
uploadInfoStore?.setUploadInfo({
open: true,
list: json,
isPermanence: uploadInfoIsPermanence,
});
} else {
uploadInfoList.map((item) => {
if (item.id === timeId) {
item["statusMsg"] = "上传成功";
}
});
uploadInfoStore?.setUploadInfo({
open: true,
list: uploadInfoList,
isPermanence: uploadInfoIsPermanence,
});
}
callBack && callBack(upload);
},
});
// Start the upload
upload.start();
};
const uploadFileFunc = (
file,
url,
filepath,
page,
length,
allFile,
path,
timeId,
callBack
) => {
// Create a new tus upload
for (let i in localStorage) {
if (i.indexOf("tus::tus-br") > -1) {
localStorage.removeItem(i);
}
}
let timeIdFile = new Date().getTime();
let headers = {
username: "",
token: "",
filetoken: "",
share: false,
};
let uploads = new tus.Upload(file, {
endpoint: url,
parallelUploads: 1,
chunkSize: 5242880,
metadata: {
filepath: filepath,
},
retryDelays: [0, 3000, 5000, 10000, 20000],
headers: headers,
onError: function (error) {
console.log("Failed because: " + error);
},
onProgress: function (bytesUploaded, bytesTotal, percentage) {
// console.log("正在上传的文件名:" + uploads['file']['name'], 'onProgress')
if (
uploadInfoList.filter((item) => item.id === timeId) &&
uploadInfoList.filter((item) => item.id === timeId).length > 0
) {
let k = uploadInfoList;
k.map((item) => {
if (item.id === timeId) {
item["upload"] = uploads;
}
});
uploadInfoStore?.setUploadInfo({
open: true,
list: k,
isPermanence: uploadInfoIsPermanence,
});
return;
}
let json = uploadInfoList.concat({
name: allFile[page]["path"].split("/")[0],
bytesUploaded: page + 1,
statusMsg: "正在上传",
bytesTotal: length,
upload: uploads,
ids: timeIdFile,
percentage: ((page + 1) / length) * 100,
type: "folder",
id: timeId,
});
uploadInfoStore?.setUploadInfo({
open: true,
list: json,
isPermanence: uploadInfoIsPermanence,
});
},
onSuccess: function (bytesUploaded, bytesTotal, percentage) {
++page;
// 每次成功 page累加 当page 与 总上传文件长度 进行比较 判断是否上传文件夹是否成功。
if (page >= length) {
uploadInfoList.map((item) => {
if (item.id === timeId) {
item["statusMsg"] = "上传成功";
item["bytesUploaded"] = length;
item["bytesTotal"] = length;
item["percentage"] = 100;
}
});
uploadInfoStore?.setUploadInfo({
open: uploadInfoOpen,
list: uploadInfoList,
isPermanence: uploadInfoIsPermanence,
});
// 上传文件夹成功 回调 页面 刷新 列表 重新请求数据
callBack && callBack(true);
return;
} else {
// 判断 传输列表中是否有 有该 id 的任务
// 进度 判断: 成功一个文件 page 累加 redux
if (
uploadInfoList((item) => item.id === timeId) &&
uploadInfoList((item) => item.id === timeId).length > 0
) {
let newList = uploadInfoList;
newList.forEach((items) => {
if (items.id === timeId) {
items["name"] = allFile[page]["path"].split("/")[0];
items["bytesUploaded"] = page + 1;
items["bytesTotal"] = length;
items["statusMsg"] = "正在上传";
items["percentage"] = ((page + 1) / length) * 100;
}
});
uploadInfoStore?.setUploadInfo({
open: true,
list: newList.concat([]),
isPermanence: uploadInfoIsPermanence,
});
}
uploadFileFunc(
allFile[page],
url,
path === "/"
? path + allFile[page]["path"]
: path + "/" + allFile[page]["path"],
page,
allFile.length,
allFile,
path,
timeId,
callBack
);
}
},
});
// 每次调用 把 任务 重新赋值给 该上传任务 以便于 文件夹暂停下载功能实现
if (
uploadInfoList.filter((item) => item.id === timeId) &&
uploadInfoList.filter((item) => item.id === timeId).length > 0
) {
let k = uploadInfoList;
k.map((item) => {
if (item.id === timeId) {
item["upload"] = uploads;
}
});
uploadInfoStore?.setUploadInfo({
open: true,
list: k,
isPermanence: uploadInfoIsPermanence,
});
}
uploads.start();
};
const uploadFolder = (file, url, filepath, callBack) => {
// tus 上传会设置 缓存 清除缓存设置
for (let i in localStorage) {
if (i.indexOf("tus::tus-br") > -1) {
localStorage.removeItem(i);
}
}
// 打开传输列表
uploadInfoStore?.setUploadInfoIsPermanence(false);
// 判断 文件夹中 是否中 是否 全部是中文 不是 过滤 文件路径中文或者特殊符号 含有任务的
let filterFileJson = [];
if (file && file.length > 0) {
filterFileJson = file.filter((item) =>
verifyLettersNumbersCertainChars5(item.path)
);
}
if (filterFileJson && filterFileJson.length === 0) {
let json1 = uploadInfoList.concat({
name: file[0]["path"].split("/")[0],
bytesUploaded: 0,
bytesTotal: 0,
percentage: 0,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
bytesUploaded2: 0,
fileIsCn: true,
statusMsg: "上传失败",
type: true,
statusMsgDetail:
"上传失败,文件或文件夹的命名长度不超过127字节,不支持特殊符号、空格。",
// 已自动过滤掉命名包含中文、特殊符号、空格的文件及文件夹
upload: null,
id: new Date().getTime(),
dir: "/home/cloudam/",
});
uploadInfoStore?.setUploadInfo({
open: true,
list: json1,
isPermanence: false,
});
return;
}
let timeId = new Date().getTime();
if (filterFileJson && filterFileJson.length < file.length) {
let json1 = uploadInfoList.concat({
name: file[0]["path"].split("/")[0],
bytesUploaded: 0,
bytesTotal: filterFileJson.length,
percentage: 0,
startTime: new Date().getTime(),
endTime: new Date().getTime() + 1000,
id: timeId,
type: true,
statusMsg: "正在上传",
statusMsgDetail: "已自动过滤掉命名包含特殊符号、空格的文件及文件夹",
});
uploadInfoStore?.setUploadInfo({
open: true,
list: json1,
isPermanence: false,
});
}
let page = 0;
file = filterFileJson;
uploadFileFunc(
file[page],
url,
filepath === "/"
? filepath + file[page]["path"]
: filepath + "/" + file[page]["path"],
page,
file.length,
file,
filepath,
timeId,
callBack
);
return file;
// Start the upload
};
return {
uploadFile,
uploadFileCallBack,
uploadFolder,
uploadFileFunc,
};
};
export default UseTusUpload;
/*
* @Author: 吴永生#A02208 yongsheng.wu@wholion.com
* @Date: 2022-06-13 17:23:49
* @LastEditors: 吴永生#A02208 yongsheng.wu@wholion.com
* @LastEditTime: 2022-06-13 17:28:59
* @FilePath: /bkunyun/src/utils/helper.ts
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
const getTrueLength = (str: string) => {//获取字符串的真实长度(字节长度)
let len = str.length, truelen = 0;
for (let x = 0; x < len; x++) {
if (str.charCodeAt(x) > 128) {
truelen += 2;
} else {
truelen += 1;
}
}
return truelen;
}
export const verifyLettersNumbersCertainChars4 = (str: string) => {
if (str.slice(0, 1) === ".") {
return false;
}
if (getTrueLength(str) > 127) {
return false;
}
let validString = /^[\u4e00-\u9fa5_0-9a-zA-Z-_.]+$/;
return validString.test(str);
};
export const verifyLettersNumbersCertainChars5 = (str: string) => {
if (str.slice(0, 1) === ".") {
return false;
}
if (getTrueLength(str) > 127) {
return false;
}
let validString = /^[\u4e00-\u9fa5_0-9a-zA-Z\/-_.]+$/;
return validString.test(str);
};
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment