mirror of
https://code.equilibrium.co.ao/ITO/doneit-web.git
synced 2026-04-18 12:37:53 +00:00
video uploader
This commit is contained in:
@@ -14,8 +14,10 @@ import { FileValidatorService } from "src/app/services/file/file-validator.servi
|
||||
import { MiddlewareServiceService } from "src/app/shared/API/middleware/middleware-service.service";
|
||||
import { LakefsRepositoryService } from '../../repository/lakefs/lakefs-repository.service';
|
||||
import { ok, err, Result } from 'neverthrow';
|
||||
import { SocketConnectionMCRService } from "src/app/services/socket-connection-mcr.service"
|
||||
import { CMAPIService } from "src/app/shared/repository/CMAPI/cmapi.service";
|
||||
import { ObjectMergeNotification, SocketConnectionMCRService } from "src/app/services/socket-connection-mcr.service"
|
||||
import { CMAPIService } from '../../repository/CMAPI/cmapi.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
|
||||
enum ActionType {
|
||||
newRapid = "1",
|
||||
@@ -338,6 +340,7 @@ export class NewPublicationPage implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(this.seletedContent.length == 0) {
|
||||
|
||||
const newAttachment = new PublicationAttachmentEntity(
|
||||
@@ -356,6 +359,7 @@ export class NewPublicationPage implements OnInit {
|
||||
if (this.publicationType == ActionType.edit) {
|
||||
|
||||
|
||||
|
||||
if (this.seletedContent.length >= 1) {
|
||||
const loader = this.toastService.loading()
|
||||
|
||||
@@ -370,6 +374,22 @@ export class NewPublicationPage implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
this.publicationFormMV.setDataToFrom(this.publication)
|
||||
const upload = await this.publicationFormMV.uploadVideosFiles()
|
||||
|
||||
if(upload) {
|
||||
this.publication.Files = this.publication.Files.map((e:PublicationAttachmentEntity)=> {
|
||||
if(e.FileType == 'video') {
|
||||
e.FileBase64 = environment.apiURL + "/ObjectServer/StreamFiles?path="+ e.chucksManager.path
|
||||
}
|
||||
|
||||
return e
|
||||
})
|
||||
|
||||
console.log("this.publication.Files", this.publication.Files)
|
||||
}
|
||||
|
||||
|
||||
this.publication.Files = this.publication.Files.map( e => ({
|
||||
FileBase64: e.FileBase64,
|
||||
FileExtension: e.FileExtension,
|
||||
@@ -416,6 +436,20 @@ export class NewPublicationPage implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
this.publicationFormMV.setDataToFrom(this.publication)
|
||||
const upload = await this.publicationFormMV.uploadVideosFiles()
|
||||
|
||||
if(upload) {
|
||||
this.publication.Files = this.publication.Files.map((e:PublicationAttachmentEntity)=> {
|
||||
if(e.FileType == 'video') {
|
||||
e.FileBase64 = environment.apiURL + "/ObjectServer/StreamFiles?path="+ e.chucksManager.path
|
||||
}
|
||||
|
||||
return e
|
||||
})
|
||||
|
||||
console.log("this.publication.Files", this.publication.Files)
|
||||
}
|
||||
|
||||
this.publication.Files = this.publication.Files.map( e => ({
|
||||
FileBase64: e.FileBase64,
|
||||
@@ -871,7 +905,7 @@ export class NewPublicationPage implements OnInit {
|
||||
|
||||
|
||||
|
||||
uploadChunk() {
|
||||
async uploadChunk() {
|
||||
let time = new Date()
|
||||
|
||||
this.publication = {
|
||||
@@ -886,162 +920,95 @@ export class NewPublicationPage implements OnInit {
|
||||
}
|
||||
|
||||
|
||||
this.publicationFormMV.setDataToFrom(this.publication)
|
||||
this.publicationFormMV.uploadVideosFiles()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// class UploadFileUseCase {
|
||||
// LakefsRepositoryService: LakefsRepositoryService = window["LakefsRepositoryService"]
|
||||
// constructor() {}
|
||||
// execute(attachment: PublicationAttachmentEntity) {
|
||||
|
||||
// const file: File = attachment.blob
|
||||
|
||||
// const chunkSize = 1024 * 100; // Adjust the chunk size as needed
|
||||
// const fileSize = file.size;
|
||||
// let uploadedSize = 0
|
||||
// const totalChunks = Math.ceil(fileSize / chunkSize);
|
||||
// let offset = 0;
|
||||
// let i = 1;
|
||||
// let j = 0;
|
||||
// let path;
|
||||
|
||||
// function count () {
|
||||
// j++
|
||||
// return j
|
||||
// }
|
||||
|
||||
// const readAndUploadChunk = async(index: number) => {
|
||||
// return new Promise<void>((resolve, reject) => {
|
||||
// const chunk = file.slice(offset, offset + chunkSize);
|
||||
// const reader = new FileReader();
|
||||
|
||||
// reader.onload = async () => {
|
||||
// const blob = new Blob([reader.result as ArrayBuffer]);
|
||||
// const formData = new FormData();
|
||||
// const file = new File([blob], "test.mp4", { type: blob.type });
|
||||
|
||||
// uploadedSize =+ file.size
|
||||
|
||||
// formData.append("blobFile", file);
|
||||
// formData.append("length", totalChunks.toString());
|
||||
// formData.append("index", index.toString());
|
||||
// formData.append("path", path);
|
||||
|
||||
// try {
|
||||
// const response = await this.LakefsRepositoryService.uploadFile(formData).toPromise()
|
||||
|
||||
// console.log({response})
|
||||
|
||||
// resolve()
|
||||
// } catch (erro) {
|
||||
// reject()
|
||||
// }
|
||||
|
||||
// };
|
||||
|
||||
// reader.readAsArrayBuffer(chunk);
|
||||
// offset += chunkSize;
|
||||
// });
|
||||
// }
|
||||
|
||||
// const loop = async() => {
|
||||
|
||||
// for (let index = 2; index <= totalChunks; index++) {
|
||||
// await readAndUploadChunk(index);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// const startUpload = async() => {
|
||||
// const index = count();
|
||||
// const chunk = file.slice(offset, offset + chunkSize);
|
||||
// const reader = new FileReader();
|
||||
|
||||
// reader.onload = async () => {
|
||||
// const blob = new Blob([reader.result as ArrayBuffer]);
|
||||
// const formData = new FormData();
|
||||
// const file = new File([blob], "test.mp4", { type: blob.type });
|
||||
// uploadedSize =+ file.size
|
||||
// formData.append("blobFile", file);
|
||||
// formData.append("length", totalChunks.toString());
|
||||
// formData.append("index", index.toString());
|
||||
|
||||
|
||||
// const response: any = await this.LakefsRepositoryService.uploadFile(formData).toPromise()
|
||||
|
||||
// console.log({ response, index });
|
||||
// if (index === 1) {
|
||||
// path = response.path;
|
||||
// }
|
||||
|
||||
// await loop();
|
||||
// };
|
||||
|
||||
// reader.readAsArrayBuffer(chunk);
|
||||
// offset += chunkSize;
|
||||
// }
|
||||
|
||||
// startUpload();
|
||||
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
class UploadFileUseCase {
|
||||
CMAPIService: CMAPIService = window["CMAPIService"]
|
||||
CMAPIService: CMAPIService = window["CMAPIAPIRepository"]
|
||||
constructor() {}
|
||||
async execute(ChucksManager: ChucksManager): Promise<Result<ChucksManager, ChucksManager>> {
|
||||
async execute(PublicationAttachmentEntity: PublicationAttachmentEntity): Promise<Result<PublicationAttachmentEntity, PublicationAttachmentEntity>> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
||||
let path: string;
|
||||
const length = ChucksManager.chunks.totalChunks.toString()
|
||||
|
||||
const readAndUploadChunk = async(index: number) => {
|
||||
let path: string;
|
||||
const length = PublicationAttachmentEntity.chucksManager.chunks.totalChunks.toString()
|
||||
|
||||
const chunk = await ChucksManager.chunks.getChunks(index)
|
||||
const blob = new Blob([chunk]);
|
||||
const blobFile = new File([blob], "test.mp4", { type: blob.type });
|
||||
const readAndUploadChunk = async(index: number) => {
|
||||
|
||||
return await this.CMAPIService.FileContent({length, path: ChucksManager.path, index, blobFile})
|
||||
}
|
||||
const chunk = await PublicationAttachmentEntity.chucksManager.chunks.getChunks(index)
|
||||
const blob = new Blob([chunk]);
|
||||
const blobFile = new File([blob], "test.mp4", { type: blob.type });
|
||||
|
||||
if(!ChucksManager.hasPath()) {
|
||||
|
||||
const initIndex = ChucksManager.uploadsCount + 1
|
||||
const chuck = await ChucksManager.chunks.getChunks(initIndex)
|
||||
const blob = new Blob([chuck]);
|
||||
const blobFile = new File([blob], "test.mp4", { type: blob.type });
|
||||
|
||||
const uploadRequest = await this.CMAPIService.FileContent({length, path:ChucksManager.path, index: initIndex, blobFile})
|
||||
|
||||
if(uploadRequest.isOk()) {
|
||||
|
||||
path = uploadRequest.value.data
|
||||
|
||||
ChucksManager.setPath(path)
|
||||
ChucksManager.setResponse(initIndex, uploadRequest.value as any)
|
||||
} else {
|
||||
return err(ChucksManager)
|
||||
return await this.CMAPIService.FileContent({length, path: PublicationAttachmentEntity.chucksManager.path, index, blobFile})
|
||||
}
|
||||
}
|
||||
|
||||
const indexContinuation = ChucksManager.uploadsCount + 1
|
||||
for (let index = indexContinuation; index <= ChucksManager.chunks.totalChunks; index++) {
|
||||
const uploadRequest = await readAndUploadChunk(index)
|
||||
if(!PublicationAttachmentEntity.chucksManager.hasPath()) {
|
||||
const initIndex = 1
|
||||
|
||||
const uploadRequest = await readAndUploadChunk(initIndex)
|
||||
|
||||
if(uploadRequest.isOk()) {
|
||||
|
||||
path = uploadRequest.value.data
|
||||
|
||||
PublicationAttachmentEntity.chucksManager.setPath(path)
|
||||
PublicationAttachmentEntity.chucksManager.setResponse(initIndex, uploadRequest)
|
||||
} else {
|
||||
reject(err(PublicationAttachmentEntity))
|
||||
}
|
||||
}
|
||||
|
||||
const allRequest: Promise<any>[] = []
|
||||
|
||||
for (let index = 2; index <= PublicationAttachmentEntity.chucksManager.chunks.totalChunks -1; index++) {
|
||||
const needUpload = PublicationAttachmentEntity.chucksManager.needToUploadChunkIndex(index)
|
||||
|
||||
if(needUpload) {
|
||||
|
||||
const request = readAndUploadChunk(index).then(async(uploadRequest) => {
|
||||
if(uploadRequest.isErr()) {
|
||||
const pingRequest = await this.CMAPIService.ping()
|
||||
if( pingRequest.isErr()) {
|
||||
reject(err(PublicationAttachmentEntity))
|
||||
}
|
||||
} else {
|
||||
PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
|
||||
}
|
||||
})
|
||||
allRequest.push(request)
|
||||
|
||||
// const request = readAndUploadChunk(index)
|
||||
// const uploadRequest = await request
|
||||
|
||||
// allRequest.push(request)
|
||||
// if(uploadRequest.isErr()) {
|
||||
// const pingRequest = await this.CMAPIService.ping()
|
||||
// if( pingRequest.isErr()) {
|
||||
// reject(err(PublicationAttachmentEntity))
|
||||
// }
|
||||
// } else {
|
||||
// PublicationAttachmentEntity.chucksManager.setResponse(index, uploadRequest)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(allRequest)
|
||||
|
||||
const uploadRequest = await readAndUploadChunk(PublicationAttachmentEntity.chucksManager.chunks.totalChunks)
|
||||
if(uploadRequest.isErr()) {
|
||||
return err(ChucksManager)
|
||||
const pingRequest = await this.CMAPIService.ping()
|
||||
if( pingRequest.isErr()) {
|
||||
reject(err(PublicationAttachmentEntity))
|
||||
}
|
||||
} else {
|
||||
ChucksManager.setResponse(index, uploadRequest.value as any)
|
||||
PublicationAttachmentEntity.chucksManager.setResponse(PublicationAttachmentEntity.chucksManager.chunks.totalChunks, uploadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
return ok(ChucksManager)
|
||||
PublicationAttachmentEntity.chucksManager.doneChunkUpload()
|
||||
resolve(ok(PublicationAttachmentEntity))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1084,6 +1051,9 @@ class PublicationAttachmentEntity {
|
||||
setChunkManger (chunks: Chunks) {
|
||||
this.chucksManager = new ChucksManager({chunks})
|
||||
}
|
||||
get hasChunkManger() {
|
||||
return this.chucksManager?.chunks
|
||||
}
|
||||
|
||||
get hasChunkManager() {
|
||||
return this.chucksManager != null
|
||||
@@ -1111,8 +1081,14 @@ class PublicationFormModel implements IPublicationFormModelEntity {
|
||||
OriginalFileName: string;
|
||||
Files: PublicationAttachmentEntity[];
|
||||
|
||||
hasSet = false
|
||||
|
||||
setData(data: IPublicationFormModelEntity) {
|
||||
Object.assign(this, data)
|
||||
if(!this.hasSet) {
|
||||
Object.assign(this, data)
|
||||
}
|
||||
|
||||
this.hasSet = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,6 +1096,7 @@ class PublicationFormMV {
|
||||
|
||||
private UploadFileUseCase = new UploadFileUseCase()
|
||||
private form = new PublicationFormModel()
|
||||
private ObjectMergeNotification = new ObjectMergeNotification()
|
||||
|
||||
setDataToFrom(data: IPublicationFormModelEntity) {
|
||||
this.form.setData(data)
|
||||
@@ -1129,30 +1106,76 @@ class PublicationFormMV {
|
||||
return this.form.Files.filter( x => x.FileType == 'video')
|
||||
}
|
||||
|
||||
private async upload(PublicationAttachmentEntity: PublicationAttachmentEntity) {
|
||||
private upload(PublicationAttachmentEntity: PublicationAttachmentEntity) {
|
||||
|
||||
const fileBlob = PublicationAttachmentEntity.blobFile;
|
||||
const fileChunks = new Chunks({chunkSize: 100 })
|
||||
fileChunks.setFile(fileBlob)
|
||||
return new Promise(async (resolve, reject)=> {
|
||||
|
||||
PublicationAttachmentEntity.setChunkManger(fileChunks)
|
||||
if(!PublicationAttachmentEntity.hasChunkManger) {
|
||||
const fileBlob = PublicationAttachmentEntity.blobFile;
|
||||
const fileChunks = new Chunks({chunkSize: 500 })
|
||||
fileChunks.setFile(fileBlob)
|
||||
|
||||
const ChucksManagers = new ChucksManager({chunks: fileChunks})
|
||||
PublicationAttachmentEntity.setChunkManger(fileChunks)
|
||||
|
||||
PublicationAttachmentEntity.chucksManager.registerOnLastChunk(()=> {
|
||||
const guid = PublicationAttachmentEntity.chucksManager.path
|
||||
|
||||
this.ObjectMergeNotification.subscribe(guid, (data) => {
|
||||
// console.log("data", data)
|
||||
PublicationAttachmentEntity
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
|
||||
} else {
|
||||
if(PublicationAttachmentEntity.chucksManager.doneUpload) {
|
||||
return resolve(true)
|
||||
}
|
||||
}
|
||||
|
||||
const result = await this.UploadFileUseCase.execute(PublicationAttachmentEntity)
|
||||
|
||||
if(result.isErr()) {
|
||||
reject(false)
|
||||
}
|
||||
})
|
||||
|
||||
this.UploadFileUseCase.execute(ChucksManagers)
|
||||
}
|
||||
|
||||
uploadVideosFiles() {
|
||||
uploadVideosFiles(): Promise<Boolean> {
|
||||
return new Promise((resolve, reject)=> {
|
||||
const videosFiles = this.getVideoFiles()
|
||||
|
||||
const videosFiles = this.getVideoFiles()
|
||||
const videosFilesToUploads = videosFiles.filter( e => e.toUpload == true)
|
||||
|
||||
const videosFilesToUploads = videosFiles.filter( e => e.toUpload == true)
|
||||
const Promises: Promise<any>[] = []
|
||||
|
||||
for(const file of videosFilesToUploads) {
|
||||
const promise = this.upload(file)
|
||||
Promises.push(promise)
|
||||
}
|
||||
|
||||
// Use Promise.all to wait for all promises to resolve
|
||||
Promise.all(Promises)
|
||||
.then((results) => {
|
||||
// Check if every promise resolved successfully
|
||||
const allPromisesResolvedSuccessfully = results.every((result) => result == true);
|
||||
|
||||
if (allPromisesResolvedSuccessfully) {
|
||||
console.log('All promises resolved successfully.');
|
||||
resolve(true)
|
||||
} else {
|
||||
reject(false)
|
||||
console.log('Some promises failed to resolve successfully.');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(false)
|
||||
console.error('An error occurred while resolving promises:', error);
|
||||
});
|
||||
})
|
||||
|
||||
for(const file of videosFilesToUploads) {
|
||||
this.upload(file)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1205,7 +1228,7 @@ class Chunks {
|
||||
}
|
||||
|
||||
interface IUploadResponse {
|
||||
result: Result<string, Error>
|
||||
result: Result<any, Error>
|
||||
attemp: number
|
||||
}
|
||||
|
||||
@@ -1213,25 +1236,110 @@ class ChucksManager {
|
||||
chunks: Chunks
|
||||
uploads: {[key: string]: IUploadResponse } = {}
|
||||
path: string = undefined
|
||||
uploadPercentage: string = "0%"
|
||||
merging = false
|
||||
onSetPath: Function[] = []
|
||||
onSetLastChunk: Function[] = []
|
||||
contentReady = false
|
||||
|
||||
getUploadPercentage() {
|
||||
return this.uploadPercentage
|
||||
}
|
||||
|
||||
get uploadsCount() {
|
||||
return Object.entries(this.uploads).length
|
||||
}
|
||||
|
||||
get uploadWithSuccessCount() {
|
||||
const uploadWithSuccess = Object.entries(this.uploads).filter(([index, data])=> data.result.isOk())
|
||||
return uploadWithSuccess.length
|
||||
}
|
||||
|
||||
get doneUpload() {
|
||||
return this.chunks.totalChunks == this.uploadWithSuccessCount
|
||||
}
|
||||
|
||||
uploadFunc: Function
|
||||
constructor({chunks}) {
|
||||
this.chunks = chunks
|
||||
}
|
||||
|
||||
calculatePercentage(): number {
|
||||
/**
|
||||
* Calculate the percentage based on the total and current values.
|
||||
*
|
||||
* @param total - The total value.
|
||||
* @param current - The current value.
|
||||
* @returns The percentage calculated as (current / total) * 100.
|
||||
*/
|
||||
const total = this.chunks.totalChunks
|
||||
const current = this.uploadWithSuccessCount
|
||||
|
||||
if (total === 0) {
|
||||
return 0; // To avoid division by zero error
|
||||
}
|
||||
|
||||
const percentage: number = (current / total) * 100;
|
||||
return percentage;
|
||||
}
|
||||
|
||||
setPercentage() {
|
||||
const percentage: number = this.calculatePercentage()
|
||||
console.log({percentage})
|
||||
this.uploadPercentage = percentage.toString()+"%"
|
||||
}
|
||||
|
||||
setPath(path: string) {
|
||||
this.path = path
|
||||
this.onSetPath.forEach(callback => callback());
|
||||
}
|
||||
|
||||
registerOnSetPath(a: Function) {
|
||||
this.onSetPath.push(a)
|
||||
}
|
||||
|
||||
registerOnLastChunk(a: Function) {
|
||||
this.onSetPath.push(a)
|
||||
}
|
||||
|
||||
hasPath() {
|
||||
return this.path != undefined
|
||||
}
|
||||
|
||||
isIndexRegistered(index) {
|
||||
if(!this.uploads[index]) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
needToUploadChunkIndex(index) {
|
||||
return !this.uploads?.[index]?.result?.isOk()
|
||||
}
|
||||
|
||||
setResponse(index, UploadResponse) {
|
||||
this.uploads[index] = UploadResponse
|
||||
|
||||
if(!this.isIndexRegistered(index)) {
|
||||
this.uploads[index] = {
|
||||
attemp: 1,
|
||||
result: UploadResponse
|
||||
}
|
||||
console.log({UploadResponse})
|
||||
} else {
|
||||
this.uploads[index].attemp++;
|
||||
this.uploads[index].result = UploadResponse
|
||||
}
|
||||
|
||||
this.setPercentage()
|
||||
}
|
||||
|
||||
doneChunkUpload() {
|
||||
this.merging = true
|
||||
this.onSetLastChunk.forEach(callback => callback());
|
||||
}
|
||||
|
||||
contentSetReady() {
|
||||
this.merging = false
|
||||
this.contentReady = true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user