started folder upload changes
This commit is contained in:
@@ -17,6 +17,12 @@ interface RequestType extends Request {
|
||||
encryptedToken?: string;
|
||||
}
|
||||
|
||||
interface RequestTypeFullUser extends Request {
|
||||
user?: UserInterface;
|
||||
encryptedToken?: string;
|
||||
accessTokenStreamVideo?: string;
|
||||
}
|
||||
|
||||
const chunkService = new ChunkService();
|
||||
|
||||
class FolderController {
|
||||
@@ -65,6 +71,34 @@ class FolderController {
|
||||
}
|
||||
};
|
||||
|
||||
uploadFolder = async (
|
||||
req: RequestTypeFullUser,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
if (!req.user) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const user = req.user;
|
||||
const busboy = req.busboy;
|
||||
|
||||
console.log("upload folder request");
|
||||
|
||||
busboy.on("error", (e: Error) => {
|
||||
console.log("busboy error", e);
|
||||
// handleError();
|
||||
});
|
||||
|
||||
req.pipe(busboy);
|
||||
|
||||
await chunkService.uploadFolder(user, busboy, req);
|
||||
} catch (e) {
|
||||
console.log("upload folder error", e);
|
||||
}
|
||||
};
|
||||
|
||||
deleteAll = async (req: RequestType, res: Response, next: NextFunction) => {
|
||||
if (!req.user) {
|
||||
return;
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
restoreFolderValidationRules,
|
||||
trashFolderValidationRules,
|
||||
} from "../middleware/folders/folder-middleware";
|
||||
import authFullUser from "../middleware/authFullUser";
|
||||
|
||||
const folderController = new FolderController();
|
||||
const router = Router();
|
||||
@@ -97,4 +98,10 @@ router.post(
|
||||
folderController.createFolder
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/folder-service/upload",
|
||||
authFullUser,
|
||||
folderController.uploadFolder
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -22,6 +22,7 @@ import UserDB from "../../db/mongoDB/userDB";
|
||||
import fixEndChunkLength from "./utils/fixEndChunkLength";
|
||||
import archiver from "archiver";
|
||||
import async from "async";
|
||||
import getFolderBusboyData from "./utils/getFolderUploadBusboyData";
|
||||
|
||||
const fileDB = new FileDB();
|
||||
const folderDB = new FolderDB();
|
||||
@@ -129,7 +130,21 @@ class StorageService {
|
||||
};
|
||||
};
|
||||
|
||||
uploadFolder = async (user: UserInterface, busboy: any, req: Request) => {};
|
||||
uploadFolder = async (user: UserInterface, busboy: any, req: Request) => {
|
||||
const password = user.getEncryptionKey();
|
||||
|
||||
if (!password) throw new ForbiddenError("Invalid Encryption Key");
|
||||
|
||||
const initVect = crypto.randomBytes(16);
|
||||
|
||||
const CIPHER_KEY = crypto.createHash("sha256").update(password).digest();
|
||||
|
||||
const cipher = crypto.createCipheriv("aes256", CIPHER_KEY, initVect);
|
||||
|
||||
const fileData = await getFolderBusboyData(busboy);
|
||||
|
||||
console.log("file data", fileData);
|
||||
};
|
||||
|
||||
downloadFile = async (user: UserInterface, fileID: string, res: Response) => {
|
||||
const currentFile = await fileDB.getFileInfo(fileID, user._id.toString());
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { Stream } from "stream";
|
||||
|
||||
const getFolderBusboyData = (busboy: any) => {
|
||||
type dataType = Record<string, any>;
|
||||
|
||||
return new Promise<dataType>((resolve, reject) => {
|
||||
const formData = new Map();
|
||||
|
||||
let filesProcessed = 0;
|
||||
let filesToProcess = 0;
|
||||
|
||||
const fileDataMap: dataType = {};
|
||||
|
||||
busboy.on("field", (field: any, val: any) => {
|
||||
if (typeof val !== "string" || val !== "undefined") {
|
||||
formData.set(field, val);
|
||||
if (field === "file-data") {
|
||||
const fileData = JSON.parse(val);
|
||||
console.log("file data", fileData);
|
||||
fileDataMap[fileData.path] = {
|
||||
...fileData,
|
||||
};
|
||||
}
|
||||
if (field === "total-files") {
|
||||
filesToProcess = +val;
|
||||
console.log("total files", filesToProcess);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
busboy.on(
|
||||
"file",
|
||||
async (
|
||||
data: string,
|
||||
file: Stream,
|
||||
fileData: {
|
||||
filename: string;
|
||||
}
|
||||
) => {
|
||||
const path = fileData.filename;
|
||||
fileDataMap[path] = {
|
||||
...fileDataMap[path],
|
||||
file,
|
||||
};
|
||||
|
||||
filesProcessed++;
|
||||
|
||||
if (filesProcessed === filesToProcess) {
|
||||
resolve(fileDataMap);
|
||||
}
|
||||
// resolve({
|
||||
// file,
|
||||
// filename,
|
||||
// formData,
|
||||
// });
|
||||
console.log("flr", fileData);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default getFolderBusboyData;
|
||||
@@ -97,6 +97,12 @@ export const createFolderAPI = async (name: string, parent?: string) => {
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const uploadFolderAPI = async (data: FormData, config: any) => {
|
||||
const url = "/folder-service/upload";
|
||||
const response = await axios.post(url, data, config);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// PATCH
|
||||
|
||||
export const renameFolder = async (folderID: string, name: string) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
import { createFolderAPI } from "../../api/foldersAPI";
|
||||
import { createFolderAPI, uploadFolderAPI } from "../../api/foldersAPI";
|
||||
import { useFoldersClient } from "../../hooks/folders";
|
||||
import { useClickOutOfBounds } from "../../hooks/utils";
|
||||
import { showCreateFolderPopup } from "../../popups/folder";
|
||||
@@ -17,7 +17,8 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
const { invalidateFoldersCache } = useFoldersClient();
|
||||
const { wrapperRef } = useClickOutOfBounds(props.closeDropdown);
|
||||
const uploadRef: RefObject<HTMLInputElement> = useRef(null);
|
||||
const { uploadFiles } = useUploader();
|
||||
const uploadFolderRef: RefObject<HTMLInputElement> = useRef(null);
|
||||
const { uploadFiles, uploadFolder } = useUploader();
|
||||
|
||||
const createFolder = async () => {
|
||||
props.closeDropdown();
|
||||
@@ -41,12 +42,31 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
uploadFiles(files);
|
||||
};
|
||||
|
||||
const handleFolderUpload = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
props.closeDropdown();
|
||||
|
||||
const items = uploadFolderRef.current?.files;
|
||||
|
||||
if (!items) return;
|
||||
|
||||
console.log("items", items);
|
||||
|
||||
uploadFolder(items);
|
||||
};
|
||||
|
||||
const triggerFileUpload = () => {
|
||||
if (uploadRef.current) {
|
||||
uploadRef.current.click();
|
||||
}
|
||||
};
|
||||
|
||||
const triggerFolderUpload = () => {
|
||||
if (uploadFolderRef.current) {
|
||||
uploadFolderRef.current.click();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={wrapperRef} className="absolute bottom-0 top-full w-full">
|
||||
<input
|
||||
@@ -56,6 +76,14 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
multiple={true}
|
||||
onChange={handleUpload}
|
||||
/>
|
||||
<input
|
||||
className="hidden"
|
||||
ref={uploadFolderRef}
|
||||
type="file"
|
||||
// @ts-ignore
|
||||
webkitdirectory="true"
|
||||
onChange={handleFolderUpload}
|
||||
/>
|
||||
<ul className="rounded-sm overflow-hidden shadow-lg">
|
||||
<li>
|
||||
<div>
|
||||
@@ -77,6 +105,15 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
<p className="text-sm">Create Folder</p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
className="flex items-center justify-start px-5 py-3 no-underline overflow-hidden text-sm bg-white hover:bg-white-hover"
|
||||
onClick={triggerFolderUpload}
|
||||
>
|
||||
<CreateFolderIcon className="w-5 h-5 mr-2.5 text-primary" />
|
||||
<p className="text-sm">Upload Folder</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
+71
-1
@@ -26,6 +26,7 @@ import {
|
||||
} from "../utils/cancelTokenManager";
|
||||
import { debounce } from "lodash";
|
||||
import { addUpload, editUpload } from "../reducers/uploader";
|
||||
import { uploadFolderAPI } from "../api/foldersAPI";
|
||||
|
||||
export const useFiles = (enabled = true) => {
|
||||
const params = useParams();
|
||||
@@ -279,5 +280,74 @@ export const useUploader = () => {
|
||||
}
|
||||
};
|
||||
|
||||
return { uploadFiles };
|
||||
const uploadFolder = (files: FileList) => {
|
||||
const data = new FormData();
|
||||
|
||||
const parent = params.id || "/";
|
||||
|
||||
data.append("parent", parent);
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const currentFile = files[i];
|
||||
data.append(
|
||||
"file-data",
|
||||
JSON.stringify({
|
||||
name: currentFile.name,
|
||||
size: currentFile.size,
|
||||
type: currentFile.type,
|
||||
path: currentFile.webkitRelativePath,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
data.append("total-files", files.length.toString());
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const currentFile = files[i];
|
||||
console.log("current file", currentFile.webkitRelativePath);
|
||||
data.append("file", currentFile, "test");
|
||||
}
|
||||
|
||||
const CancelToken = axiosNonInterceptor.CancelToken;
|
||||
const source = CancelToken.source();
|
||||
|
||||
const config = {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
"Transfere-Encoding": "chunked",
|
||||
},
|
||||
onUploadProgress: (progressEvent: ProgressEvent<EventTarget>) => {
|
||||
const currentProgress = Math.round(
|
||||
(progressEvent.loaded / progressEvent.total) * 100
|
||||
);
|
||||
|
||||
console.log("progress", currentProgress);
|
||||
},
|
||||
cancelToken: source.token,
|
||||
};
|
||||
|
||||
uploadFolderAPI(data, config)
|
||||
.then(() => {
|
||||
// dispatch(
|
||||
// editUpload({
|
||||
// id: currentID,
|
||||
// updateData: { completed: true, progress: 100 },
|
||||
// })
|
||||
// );
|
||||
// removeFileUploadCancelToken(currentID);
|
||||
console.log("uploaded folder");
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log("Error uploading folder", e);
|
||||
// dispatch(
|
||||
// editUpload({
|
||||
// id: currentID,
|
||||
// updateData: { canceled: true },
|
||||
// })
|
||||
// );
|
||||
// removeFileUploadCancelToken(currentID);
|
||||
});
|
||||
};
|
||||
|
||||
return { uploadFiles, uploadFolder };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user