Javascript Chrome在上传文件时崩溃>;1.5 GB,角度为可恢复性JS
我正在使用resumablejs库和Angular 7。当尝试使用resumable上载文件时,它可以工作到1.5 GB,没有任何问题,但是当文件大小>1.5 GB时,它在某些情况下可以工作,在某些情况下会崩溃。不确定是什么导致了问题。 它在Firefox上运行良好,没有任何问题。 我如何让它与铬一起工作 下面是组件。这里我们计算文件大小,然后在屏幕上显示它Javascript Chrome在上传文件时崩溃>;1.5 GB,角度为可恢复性JS,javascript,angular,resumablejs,Javascript,Angular,Resumablejs,我正在使用resumablejs库和Angular 7。当尝试使用resumable上载文件时,它可以工作到1.5 GB,没有任何问题,但是当文件大小>1.5 GB时,它在某些情况下可以工作,在某些情况下会崩溃。不确定是什么导致了问题。 它在Firefox上运行良好,没有任何问题。 我如何让它与铬一起工作 下面是组件。这里我们计算文件大小,然后在屏幕上显示它 export class ResumableAttachmentComponent implements Afte
export class ResumableAttachmentComponent
implements AfterViewInit, OnDestroy, OnChanges, OnInit {
@Output() fileSuccess = new EventEmitter<any>();
@Output() fileError = new EventEmitter<any>();
@Output() error = new EventEmitter<any>();
@Output() progress = new EventEmitter<any>();
@Output() pause = new EventEmitter<any>();
@Output() complete = new EventEmitter<any>();
@Output() uploadStart = new EventEmitter<any>();
@Output() uploadCancel = new EventEmitter<any>();
@Output() fileTypeError = new EventEmitter<any>();
@Output() removeBannerImage = new EventEmitter<any>();
@Output() onComponentInit = new EventEmitter<any>();
@Input() allowDirectorySelect = false;
@Input() maxFileSize = 1024 * 1024 * 1024 * 5; // 5GB
@Input() maxFiles = 1; // max number of file allowed
@Input() multiple = false;
@Input() pausable = false;
@Input() entityType: string;
@Input() entityIdentifierId: string;
@Input() categoryId: string;
@Input() chunkSize = 1024 * 1024 * 5; // 5 MB per chunk by default
@Input() checkBeforeUpload: () => boolean;
@Input() showCategory: boolean = true;
@Input() showUploadButton: boolean = true;
@Input() showDelete: boolean = false;
@Input() showUploadMessage: boolean = false;
@Input() fileType: string[] = []; // Allowing for both [extension, .extension, mime/type, mime/*]
@Input() theme: string = 'full';
@Input() permissionLevel: number;
@Input() permission: number;
@Input() bannerAttachment: any = null;
@Input() isUploadDisabled: any = false;
@Input() hasThumbnails: boolean = false;
Permissions = Permissions;
PermissionLevel = PermissionLevel;
fileSizeGreaterThanMaxAllowed = false;
numberOfFilesGreaterThanMaxAllowed = false;
// indicate that the upload is paused by user or not
paused = false;
progressBarElt: any;
querySet: boolean = false;
// text to show on the upload button depending on the fact the file upload is paused or not
uploadBtnText = localize('general_Upload');
filesToUpload: Resumable.ResumableFile[] = [];
disableUploadButton = true;
disablePauseButton = true;
disableCancelButton = true;
isChunking = false;
// @ts-ignore
resumable: Resumable;
supportResumable = false;
currentUser: IUserProfile;
baseUrl = titanApiUrl;
destroySubject = new Subject<any>();
showSelectButton: boolean;
@Input() gridSupport: {
gridData: SimpleGrid;
type: 'extend' | null;
onRowSelect: () => {};
};
resumableUploadedFiles: IResumableFileData;
backboneObservable$: Subscription;
showCommentsDialog: boolean;
tireComment: string;
constructor(
private userProfileService: UserProfileService,
private backbone: BackboneService,
private eltRef: ElementRef,
private renderer: Renderer2,
private notifyService: NotificationService,
private confirmationService: ConfirmationDialogService,
private router: Router,
private userPermissionHelper: UserPermissionHelper,
private attachmentService: AttachmentService
) {
this.currentUser = this.userProfileService.userProfile;
// cancel the file upload when user is navigating away from the page that contains the component
this.router.events
.filter(e => e instanceof NavigationStart)
.distinctUntilChanged()
.takeUntil(this.destroySubject.asObservable())
.subscribe((e: NavigationStart) => {
if (this.resumable && this.resumable.isUploading()) {
this.cancelUpload();
}
});
this.showSelectButton = true;
}
ngOnInit() {
this.checkPermission();
this.backboneObservable$ = this.backbone.message.subscribe(item => {
if (
item.type === BBMessageType.Resumable &&
item.subtype === BBMessageSubType.Resumable_Files_Attached
) {
this.resumableUploadedFiles = item.message;
}
});
this.duplicatesDialog.onSubmit = () => {
this.duplicatesDialog.show = false;
this.resumable.files.forEach(item => {
item.resumableObj.opts.query['overwrite'] =
this.duplicatesDialog.confirmedOverwrite.indexOf(
item.fileName
) >= 0;
});
};
this.onComponentInit.emit(this);
}
reset() {
// reset error flags
this.fileSizeGreaterThanMaxAllowed = false;
this.numberOfFilesGreaterThanMaxAllowed = false;
this.removeAllFiles();
this.isChunking = false;
this.paused = false;
this.uploadBtnText = localize('general_Upload');
//this.hideProgressBar = true
this.renderer.setStyle(this.progressBarElt, 'width', 0);
this.disableCancelButton = true;
this.disablePauseButton = true;
this.disableUploadButton = true;
}
ngOnDestroy() {
this.destroySubject.next();
this.backboneObservable$.unsubscribe();
}
ngAfterViewInit() {
if (!this.querySet) {
this.setResumableQuery();
}
}
hasUploadPermission: boolean = true;
ngOnChanges(changes: SimpleChanges) {
let self = this;
//If Test Template
if (
changes.hasOwnProperty('entityIdentifierId') &&
changes.entityIdentifierId.currentValue
) {
if (!self.querySet) {
self.setResumableQuery();
}
if (self.resumable) {
self.entityIdentifierId =
changes.entityIdentifierId.currentValue;
self.resumable.opts.query['entityId'] =
changes.entityIdentifierId.currentValue;
self.resumable.opts.query['entityIdentifierId'] =
changes.entityIdentifierId.currentValue;
}
}
if (changes.hasOwnProperty('entityType') && self.resumable) {
self.resumable.opts.query['entityType'] = this.entityType;
}
//Hijack query to add new/selected category id
if (changes.hasOwnProperty('categoryId') && self.resumable) {
self.resumable.opts.query['categoryId'] = this.categoryId;
}
if (changes.permission && changes.permissionLevel) {
self.hasUploadPermission = this.userPermissionHelper.checkPermission(
this.permission,
this.permissionLevel
);
}
if (changes.fileType && self.resumable) {
self.resumable.opts.fileType = this.fileType;
}
}
submitComment() {
this.resumable.opts.query['comment'] = this.tireComment;
this.resumable.upload();
this.tireComment = '';
this.showCommentsDialog = false;
}
setResumableQuery() {
let maxFileAllowed = this.multiple ? undefined : this.maxFiles; // undefined => allow to upload multiple file
//
// extra parameters to include in the multipart POST with data
let query = {};
if (this.entityType) {
query['entityType'] = this.entityType;
}
if (this.entityIdentifierId) {
query['entityIdentifierId'] = this.entityIdentifierId;
}
if (this.categoryId) {
query['categoryId'] = this.categoryId;
}
if (this.hasThumbnails) {
query['createThumbnail'] = true;
} else {
query['createThumbnail'] = false;
}
let fileUploadOptions: Resumable.ConfigurationHash = {
target: `${this.baseUrl}ResumableFile/Upload`,
simultaneousUploads: 1,
maxFiles: maxFileAllowed,
chunkSize: this.chunkSize,
forceChunkSize: true,
fileParameterName: 'file', // The name of the multipart POST parameter to use for the file chunk
query,
headers: {
userId: this.currentUser.id,
tenantId: this.currentUser.defaultTenantId
},
fileType: this.fileType,
fileTypeErrorCallback: this.onFileTypeError.bind(this)
};
// @ts-ignore
this.resumable = new Resumable(fileUploadOptions);
this.supportResumable = this.resumable.support; // check if the current browser suport resumable
// add event only if the browser support resumable upload
if (this.supportResumable) {
this.progressBarElt = this.eltRef.nativeElement.querySelector(
'.t-resumable-attachment-progress-bar-indicator'
);
let chooseFileBtn;
if (this.theme === 'icon') {
chooseFileBtn = this.eltRef.nativeElement.querySelector(
'.icon-theme-resumable'
);
} else {
chooseFileBtn = this.eltRef.nativeElement.querySelector(
'.choose-file'
);
}
if (chooseFileBtn) {
this.resumable.assignBrowse(
chooseFileBtn,
this.allowDirectorySelect
);
this.resumable.assignDrop(
this.eltRef.nativeElement.querySelector('.drop-area')
);
} else {
setTimeout(() => {
if (!this.querySet) {
this.setResumableQuery();
}
}, 400);
return;
}
this.setEvents();
}
this.querySet = true;
}
uploadTheFile() {
if (
this.checkBeforeUpload &&
typeof this.checkBeforeUpload === 'function'
) {
let checkResult = this.checkBeforeUpload();
// start the upload only if the check function return true
if (checkResult) {
// this.onUploadStart()
this.resumable.upload();
}
} else if (
this.checkBeforeUpload &&
typeof this.checkBeforeUpload !== 'function'
) {
throw new Error(
"The 'checkBeforeUpload' attribute must be a function."
);
} else {
// this.onUploadStart()
this.resumable.upload();
/* temporarily commenting the Comment popup while uploading file for Tire Model Request
if (this.entityType == 'TireModelSpecs') {
this.showCommentsDialog = true;
} else {
this.resumable.upload();
}*/
}
}
pauseFile() {
this.resumable.pause();
}
cancelUpload() {
this.resumable.cancel();
}
private setEvents() {
this.resumable.on('error', this.onError.bind(this));
this.resumable.on('fileError', this.onFileError.bind(this));
this.resumable.on('pause', this.onPause.bind(this));
this.resumable.on('complete', this.onComplete.bind(this));
this.resumable.on('fileSuccess', this.onFileSuccess.bind(this));
this.resumable.on('cancel', this.onUploadCancel.bind(this));
this.resumable.on('uploadStart', this.onUploadStart.bind(this));
//this.resumable.on('uploadStart', this.startUploadAfterCheckIsOk)
this.resumable.on('fileProgress', this.onProgress.bind(this));
this.resumable.on('fileAdded', this.onFileAdded.bind(this));
this.resumable.on('chunkingStart', this.onChunkingStart.bind(this));
this.resumable.on(
'chunkingComplete',
this.onChunkingComplete.bind(this)
);
}
@Output() onFileAdd = new EventEmitter();
private onFileAdded(file: ResumableFile, event) {
this.numberOfFilesGreaterThanMaxAllowed = false;
this.fileSizeGreaterThanMaxAllowed = false;
this.isDragOver = false;
//Getting Preview Image
let resumableFile: ResumableFile = this.resumable.files.find(item => {
// @ts-ignore
return file.file.uniqueIdentifier === item.uniqueIdentifier;
});
// @ts-ignore
resumableFile.fileReader = new FileReader();
// @ts-ignore
resumableFile.fileReader.readAsDataURL(file.file);
/**
* Show preview only if MIME type is of image type
*/
if (resumableFile.file.type.startsWith('image')) {
resumableFile.isPreviewSupported = true;
}
/**
* TODO: Check if total size was being looked at here..
*/
// @ts-ignore
if (this.resumable.getSize() > this.maxFileSize) {
this.fileSizeGreaterThanMaxAllowed = true;
this.filesToUpload = [...this.resumable.files];
} else if (
!this.multiple &&
this.resumable.files &&
this.resumable.files.length > this.maxFiles
) {
this.numberOfFilesGreaterThanMaxAllowed = true;
} else {
this.filesToUpload = [...this.resumable.files]; // get the updated list of files to upload
this.disableUploadButton = false;
this.renderer.setStyle(this.progressBarElt, 'width', 0);
}
this.disableCancelButton = false;
if (this.theme === 'icon') {
this.uploadTheFile();
} else {
this.duplicatesDialog.duplicatesArray = [];
this.checkForDuplicates();
}
this.setRealLastModifiedDate(resumableFile, file.file.lastModified);
this.onFileAdd.emit(this.filesToUpload);
}
setRealLastModifiedDate(file: ResumableFile, dateMS) {
file['resumableObj'].opts.query['documentLastModifiedByDate'] = moment(
dateMS
).format('YYYY/MM/DD HH:mm');
}
duplicatesDialog: {
duplicatesArray: any[];
confirmedOverwrite: any[];
show: boolean;
onSubmit: any;
} = {
duplicatesArray: [],
confirmedOverwrite: [],
show: false,
onSubmit: () => {}
};
checkForDuplicates() {
if (
this.resumableUploadedFiles &&
this.currentUser.tenantFeatureMap.overwriteFile &&
this.resumableUploadedFiles.categoryId === this.categoryId &&
this.resumableUploadedFiles.entityIdentifierId ===
this.entityIdentifierId
) {
this.filesToUpload.forEach(item => {
if (
this.resumableUploadedFiles.data.indexOf(item.fileName) >= 0
) {
this.duplicatesDialog.duplicatesArray.push(item.fileName);
} else {
item['resumableObj'].opts.query['overwrite'] = false;
}
});
}
if (this.duplicatesDialog.duplicatesArray.length > 0) {
this.duplicatesDialog.show = true;
}
}
private onPause() {
this.paused = true;
this.disableUploadButton = false;
this.uploadBtnText = localize('general_Resume');
this.pause.emit();
}
onComplete() {
this.complete.emit();
//Reset filesToUpload after completion
this.removeAllFiles();
}
OnRemoveBannerImg() {
this.confirmationService.setConfirm({
message: localize('general_ConformMessageForDelete'),
header: localize('general_Delete'),
accept: () => {
this.removeBannerImage.emit();
},
reject: () => {}
});
}
// `message` is the response body from the server.
private onFileSuccess(file: ResumableFile, message: any) {
if (this.showUploadMessage) {
this.notifyService.notify({
severity: 'success',
summary: localize('general_Success'),
detail: localize('general_MessageSuccessFileUploaded')
});
}
this.filesToUpload = [];
this.fileSuccess.emit({ file, message });
this.disableCancelButton = true;
this.disablePauseButton = true;
this.disableUploadButton = true;
}
// error on a specific file
private onFileError(file: ResumableFile, message: any) {
this.fileError.emit({ file, message });
}
// general error
private onError(message: any, file: ResumableFile) {
this.error.emit({ file, message });
}
onUploadStart() {
//this.hideProgressBar = false
this.uploadStart.emit(this.resumable.files.length);
this.paused = false;
this.disableUploadButton = true;
this.uploadBtnText = localize('general_Upload');
this.disableCancelButton = false;
this.disablePauseButton = false;
this.disableUploadButton = true;
}
private onProgress(file: ResumableFile) {
let fileClone: any = { ...file };
fileClone.uploaded = file.progress(false);
let totalProgress = this.resumable.progress();
let progressPercentage = Math.floor(totalProgress * 100) + '%';
this.renderer.setStyle(
this.progressBarElt,
'width',
progressPercentage
);
this.progress.emit({ file: fileClone, uploaded: totalProgress });
}
/**
* return individual file upload progress
*/
parseProgress(file: ResumableFile) {
return (
Math.round(Math.floor(file.progress(false) * 100) * 10) / 10 + '%'
);
}
private onUploadCancel() {
this.paused = false;
this.uploadBtnText = localize('general_Upload');
this.filesToUpload = this.resumable.files;
this.renderer.setStyle(this.progressBarElt, 'width', 0);
this.uploadCancel.emit();
this.disableCancelButton = true;
this.disablePauseButton = true;
this.disableUploadButton = true;
}
private removeAllFiles() {
let copy = [...this.resumable.files];
copy.forEach((f: any) => this.resumable.removeFile(f));
this.filesToUpload = this.resumable.files;
this.duplicatesDialog.confirmedOverwrite = [];
this.duplicatesDialog.duplicatesArray = [];
}
private onChunkingStart() {
this.isChunking = true;
}
private onChunkingComplete() {
this.isChunking = false;
}
private onFileTypeError(file, errorCount) {
this.fileTypeError.emit({ file, errorCount });
}
removeFile(file: any) {
this.resumable.removeFile(file);
// update the list when a file is removed
this.filesToUpload = this.resumable.files;
this.onFileAdd.emit(this.filesToUpload);
}
getFileSize(sizeInOctet: number) {
sizeInOctet = +sizeInOctet; // convert to number in case ng pass the value as string
let KB = 1024;
let MB = 1024 * 1024;
let GB = 1024 * 1024 * 1024;
if (sizeInOctet >= KB) {
if (sizeInOctet >= MB) {
if (sizeInOctet >= GB) {
return `${(sizeInOctet / GB).toFixed(2)} GB`;
}
return `${(sizeInOctet / MB).toFixed(2)} MB`;
}
return `${(sizeInOctet / KB).toFixed(2)} KB`;
}
return `${sizeInOctet} Bytes`;
}
// case multiple file
// Hide pause/resume when the upload has completed
// Show pause, hide resume on upload start
isDragOver: boolean = false;
onDrop($event) {
this.isDragOver = false;
}
allowDrop($event) {
this.isDragOver = true;
}
onLeave() {
this.isDragOver = false;
}
hasAccess: boolean = false;
hasReadAccess: boolean = false;
hasDeleteAccess: boolean = false;
hasCreateAccess: boolean = false;
checkPermission() {
if (
this.permission &&
this.permissionLevel &&
this.entityIdentifierId &&
this.entityType
) {
this.hasDeleteAccess =
this.userPermissionHelper.checkPermission(
this.permission,
PermissionLevel.Delete
) ||
this.userPermissionHelper.checkSpecialPermission(
this.permission,
PermissionLevel.Delete,
this.entityIdentifierId,
this.entityType
);
this.hasReadAccess =
this.userPermissionHelper.checkPermission(
this.permission,
PermissionLevel.Read
) ||
this.userPermissionHelper.checkSpecialPermission(
this.permission,
PermissionLevel.Read,
this.entityIdentifierId,
this.entityType
);
this.hasCreateAccess =
this.userPermissionHelper.checkPermission(
this.permission,
PermissionLevel.Create
) ||
this.userPermissionHelper.checkSpecialPermission(
this.permission,
PermissionLevel.Create,
this.entityIdentifierId,
this.entityType
);
this.hasAccess =
this.hasCreateAccess ||
this.hasDeleteAccess ||
this.hasReadAccess;
}
}
checkFileList() {
if (!this.resumable) {
return !this.isChunking;
} else {
return !this.isChunking && !this.resumable.isUploading();
}
}
downloadAttachment(id) {
this.attachmentService.download(id);
}
viewLog(id) {
this.attachmentService.getLogByDocumentId;
}
previewFileUrl: string = '';
previewDialog: boolean = false;
expandImage(previewFileUrl) {
this.previewFileUrl = previewFileUrl;
this.previewDialog = true;
}
}
导出类ResumableAttachmentComponent
实现AfterViewInit、OnDestroy、OnChanges和OnInit{
@Output()fileSuccess=neweventemitter();
@Output()fileError=neweventemitter();
@Output()错误=新的EventEmitter();
@Output()progress=neweventemitter();
@Output()pause=neweventemitter();
@Output()complete=neweventemitter();
@Output()uploadStart=neweventemitter();
@Output()uploadCancel=新的EventEmitter();
@Output()fileTypeError=neweventemitter();
@Output()removeBannerImage=新的EventEmitter();
@Output()onComponentUnit=新的EventEmitter();
@Input()allowDirectorySelect=false;
@Input()maxFileSize=1024*1024*1024*5;//5GB
@Input()maxFiles=1;//允许的最大文件数
@Input()倍数=false;
@Input()pausable=false;
@Input()entityType:字符串;
@Input()entityIdentifierId:string;
@Input()categoryId:字符串;
@Input()chunkSize=1024*1024*5;//默认情况下每个块5 MB
@Input()CheckForeUpload:()=>布尔值;
@Input()showCategory:boolean=true;
@Input()showUploadButton:boolean=true;
@Input()showDelete:boolean=false;
@Input()showUploadMessage:boolean=false;
@Input()文件类型:string[]=[];//同时允许[extension、.extension、mime/type、mime/*]
@Input()主题:字符串='full';
@Input()权限级别:数字;
@Input()权限:编号;
@Input()bannerAttachment:any=null;
@Input()isUploadDisabled:any=false;
@Input()有缩略图:boolean=false;
权限=权限;
PermissionLevel=PermissionLevel;
fileSizeGreaterThanMaxAllowed=false;
numberOfFilesGreaterThanMaxAllowed=false;
//指示上载是否由用户暂停
暂停=错误;
巴雷特:任何;
querySet:boolean=false;
//“上载”按钮上显示的文本取决于文件上载是否暂停
uploadBtnText=本地化('general_Upload');
filesToUpload:可恢复。可恢复文件[]=[];
disableUploadButton=true;
disablePauseButton=true;
disableCancelButton=true;
isChunking=假;
//@ts忽略
可恢复的:可恢复的;
SupportResubable=false;
当前用户:IUserProfile;
baseUrl=titanApiUrl;
destroySubject=新主题();
showSelectButton:布尔值;
@Input()网格支持:{
gridData:SimpleGrid;
类型:“扩展”| null;
onRowSelect:()=>{};
};
可恢复文件:IResumableFileData;
backboneObservable$:订阅;
showCommentsDialog:布尔值;
提示:字符串;
建造师(
私有userProfileService:userProfileService,
专用主干网:BackboneService,
私人eltRef:ElementRef,
私有渲染器:渲染器2,
私有notifyService:NotificationService,
私人确认服务:确认对话服务,
专用路由器:路由器,
私有userPermissionHelper:userPermissionHelper,
私有attachmentService:attachmentService
) {
this.currentUser=this.userProfileService.userProfile;
//当用户离开包含该组件的页面时,取消文件上载
这是路由器事件
.filter(e=>e导航开始的实例)
.distinctUntilChanged()
.takeUntil(this.destroySubject.asObservable())
.订阅((e:NavigationStart)=>{
if(this.resubable&&this.resubable.isUploading()){
这是cancelUpload();
}
});
this.showSelectButton=true;
}
恩戈尼尼特(){
这是checkPermission();
this.backboneObservable$=this.backbone.message.subscribe(项=>{
如果(
item.type==BBMessageType.可恢复&&
item.subtype==BBMessageSubType.resubable\u附加文件
) {
this.resumableUploadedFiles=item.message;
}
});
this.duplicatesDialog.onSubmit=()=>{
this.duplicatesDialog.show=false;
this.resubable.files.forEach(项=>{
item.resumableObj.opts.query['overwrite']=
此.duplicatesDialog.confirmDoverWrite.indexOf(
item.fileName
) >= 0;
});
};
this.onComponentUnit.emit(this);
}
重置(){
//重置错误标志
this.fileSizeGreaterThanMaxAllowed=false;
this.numberoffilegreaterthanmaxallowed=false;
这个.removeAllFiles();
this.isChunking=false;
this.pause=false;
this.uploadBtnText=本地化('general_Upload');
//this.hideProgressBar=true
this.renderer.setStyle(this.progressBarElt,'width'