Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/main/core/core_uploader/src/ |
Upload File : |
import {Type, Runtime, Loc, Dom, Event} from 'main.core'; import {EventEmitter, BaseEvent} from 'main.core.events'; import type {UploaderType, UploadQueueType} from "./types"; import DropZone from './dropzone'; import Streams from './streams'; import Options from './options'; import Package from './package'; import {appendToForm, convertFormDataToObject} from './utils'; import {UploaderQueue, UploaderUtils} from './bootstrap'; import PackageFile from "./package-file"; export default class Uploader { static repo = new Map(); static justCounter = 0; fileInput: ?Element = null; form: ?Element = null; id: string; controlId: string; CID: string; uploadFileUrl: string; limits = {}; packages: Map = new Map(); constructor(params: UploaderType) { let {input, uploadFileUrl, id, CID, controlId, dropZone, placeHolder, events} = params; if (Type.isStringFilled(uploadFileUrl)) { this.uploadFileUrl = uploadFileUrl; } input = Type.isStringFilled(input) ? document.getElementById(input): input; if (Type.isDomNode(input)) { this.fileInput = input; this.form = input.form; this.uploadFileUrl = (this.uploadFileUrl || this.form.getAttribute('action')); } else if (input !== null) { Runtime.debug(Loc.getMessage('UPLOADER_INPUT_IS_NOT_DEFINED')); return; } if (!this.uploadFileUrl) { Runtime.debug(Loc.getMessage('UPLOADER_ACTION_URL_NOT_DEFINED')) return; } this.constructor.justCounter++; const uniqueId = UploaderUtils.getId(); this.id = Type.isStringFilled(id) ? id: ['bitrixUploaderID', uniqueId].join(''); this.CID = Type.isStringFilled(CID) ? CID: ('CID' + uniqueId); // this is a security id this.controlId = (controlId || 'bitrixUploader'); // this is a control id can be lice control name this.onChange = this.onChange.bind(this); this.setLimits(params); this.initParams(params); this.init(this.fileInput); this.dropZone = this.initDropZone(dropZone); this.bindUserEvents(events); this.initFilesQueue(params); BX.onCustomEvent(window, 'onUploaderIsInited', [this.id, this]); Uploader.repo.set(this.id, this); } setLimits({uploadMaxFilesize, uploadFileWidth, uploadFileHeight, allowUpload, allowUploadExt}) { this.limits = { uploadMaxFilesize: uploadMaxFilesize || 0, uploadFileWidth: uploadFileWidth || 0, uploadFileHeight: uploadFileHeight || 0, uploadFileExt: '', uploadFile: this.fileInput ? this.fileInput.getAttribute('accept') : '', allowUpload: allowUpload, //compatibility allowUploadExt: allowUploadExt //compatibility }; const acceptAttribute = []; if (Type.isStringFilled(this.limits['uploadFile'])) { acceptAttribute.push(this.limits['uploadFile']); } if (allowUpload === 'I') { acceptAttribute.push('image/*') } if (Type.isStringFilled(allowUploadExt)) { const separator = allowUploadExt.indexOf(',') >= 0 ? ',' : ' '; const extensions = []; allowUploadExt.split(separator).forEach((extension) => { extensions.push(extension.trim().replace('.', '')); acceptAttribute.push('.' + extension.trim().replace('.', '')); }); if (extensions) { this.limits["uploadFileExt"] = extensions; } } this.limits['uploadFile'] = acceptAttribute.join(', '); } initParams({uploadMethod, uploadFormData, filesInputMultiple, uploadInputName, uploadInputInfoName, deleteFileOnServer, pasteFileHashInForm}) { // Limits this.params = { filesInputMultiple: (this.fileInput && this.fileInput["multiple"] || filesInputMultiple ? "multiple" : false), uploadFormData: (uploadFormData === "N" ? "N" : "Y"), uploadMethod: (uploadMethod === "immediate" ? "immediate" : "deferred"), uploadInputName: Type.isStringFilled(uploadInputName) ? uploadInputName : 'bxu_files', uploadInputInfoName: Type.isStringFilled(uploadInputInfoName) ? uploadInputInfoName : 'bxu_info', deleteFileOnServer: !(deleteFileOnServer === false || deleteFileOnServer === "N"), //to insert hash into the form filesInputName: (this.fileInput && this.fileInput["name"] ? this.fileInput["name"] : "FILES"), pasteFileHashInForm: !(pasteFileHashInForm === false || pasteFileHashInForm === "N") }; } init(fileInput) { if (fileInput === null) { return true; } if (Type.isDomNode(fileInput)) { const newFileInput = this.makeFileInput(fileInput); if (fileInput === this.fileInput) { this.fileInput = newFileInput; } if (newFileInput) { return true; } } return false; } initDropZone(dropZoneNode: ?Element): Object { const dropZone = new DropZone(dropZoneNode); EventEmitter.subscribe(dropZone, Options.getEventName('caught'), ({data}) => { this.onChange(data); }); EventEmitter.subscribe(this, Options.getEventName('destroy'), () => { EventEmitter.unsubscribeAll(dropZone, Options.getEventName('caught')); dropZone.destroy(); }); return dropZone; } initFilesQueue({fields, copies, placeHolder, showImage, sortItems, thumb, queueFields}) { const params = { fields: queueFields && queueFields['fields'] ? queueFields['fields'] : fields, copies: queueFields && queueFields['copies'] ? queueFields['copies'] : copies, placeHolder: queueFields && queueFields['placeHolder'] ? queueFields['placeHolder'] : placeHolder, showImage: queueFields && queueFields['showImage'] ? queueFields['showImage'] : showImage, sortItems: queueFields && queueFields['sortItems'] ? queueFields['sortItems'] : sortItems, thumb: queueFields && queueFields['thumb'] ? queueFields['thumb'] : thumb, } this.queue = new UploaderQueue(params, this.limits, this); } bindUserEvents(events:?Object) { if (!Type.isPlainObject(events)) { return; } for (let eventName in events) { if (events.hasOwnProperty(eventName)) { EventEmitter.subscribe(this, eventName, events[eventName]); } } } makeFileInput(oldFileInput) { if (!Type.isDomNode(oldFileInput)) { return false; } Event.unbindAll(oldFileInput, 'change'); const newFileInput = oldFileInput.cloneNode(true); newFileInput.value = ''; newFileInput.setAttribute('name', (this.params["uploadInputName"] + '[]')); newFileInput.setAttribute('multiple', this.params["filesInputMultiple"]); newFileInput.setAttribute('accept', this.limits["uploadFile"]); oldFileInput.parentNode.replaceChild(newFileInput, oldFileInput); BX.onCustomEvent(this, "onFileinputIsReinited", [newFileInput, this]); Event.bind(newFileInput, "change", this.onChange); return newFileInput; } onChange(event) { if (!event) { return; } if (event['preventDefault']) { event.preventDefault(); } if (event['stopPropagation']) { event.stopPropagation(); } let files = [] if (Type.isArray(event)) { files = event; } else if (Type.isObject(event)) { if (event['target']) { let fileInput = event['target']; files = fileInput.files; if (!fileInput || fileInput.disabled) { return false; } BX.onCustomEvent(this, "onFileinputIsChanged", [fileInput, this]); this.init(fileInput); } else if (event['files']) { files = event['files']; } } this.onAttach(files); return false; } onAttach(files, nodes, check: boolean) { if (!files || !files['length']) { return false; } check = (check !== false); files = [...files]; nodes = nodes && Type.isArray(nodes) ? [...nodes] : []; BX.onCustomEvent(this, "onAttachFiles", [files, nodes, this]); let added = false; [...files].forEach((file, index) => { let ext = ''; let type = (file['type'] || '').toLowerCase(); if (Type.isDomNode(file) && file.value) { ext = (file.value.name || '').split('.').pop(); } else { ext = (file['name'] || file['tmp_url'] || '').split('.').pop(); if (ext.indexOf('?') > 0) { ext = ext.substr(0, ext.indexOf('?')); } } ext = ext.toLowerCase(); if (check) { const errors = []; if ( this.limits['uploadFile'].indexOf('image/') >= 0 && ( type.indexOf('image/') < 0 && Options.getImageExtensions().indexOf(ext) < 0 ) ) { errors.push('File type is not an image like.'); } if ( this.limits['uploadFileExt'].length > 0 ) { if (this.limits['uploadFileExt'].indexOf(ext) < 0) { errors.push(`File extension ${ext} is in ${this.limits['uploadFileExt']}`); } else { errors.pop(); } } if ( this.limits['uploadMaxFilesize'] > 0 && file.size > this.limits['uploadMaxFilesize'] ) { errors.push(`File size ${file.size} is bigger than ${this.limits['uploadMaxFilesize']}`); } if (errors.length > 0) { return; } } if (String['normalize']) { file.name = String(file.name).normalize(); } BX.onCustomEvent(this, "onItemIsAdded", [file, (nodes[index] || null), this]); added = true; }); if (added && this.params["uploadMethod"] === "immediate") { this.submit(); } return false; } getFormData(): FormData { let formData = new FormData(this.params["uploadFormData"] === "Y" && this.form ? this.form : undefined); let entries = formData.entries(); let entry; while((entry = entries.next()) && entry.done === false) { const [name] = entry.value; if (name.indexOf(this.params["filesInputName"]) === 0 || name.indexOf(this.params["uploadInputInfoName"]) === 0 || name.indexOf(this.params["uploadInputName"]) === 0 ) { formData.delete(name); } } formData.append('AJAX_POST', 'Y'); formData.append('USER_ID', Loc.getMessage('USER_ID')); formData.append('sessid', BX.bitrix_sessid()); if (BX.message.SITE_ID) { formData.append('SITE_ID', BX.message.SITE_ID); } formData.append(this.params["uploadInputInfoName"] + '[controlId]', this.controlId); formData.append(this.params["uploadInputInfoName"] + '[CID]', this.CID); formData.append(this.params["uploadInputInfoName"] + '[uploadInputName]', this.params["uploadInputName"]); formData.append(this.params["uploadInputInfoName"] + '[version]', Options.getVersion()); return formData; } submit() { //region Compatibility if (this.queue.itForUpload.length <= 0) { BX.onCustomEvent(this, 'onStart', [null, {filesCount : 0}, this]); BX.onCustomEvent(this, 'onDone', [null, null, {filesCount : 0}]); BX.onCustomEvent(this, 'onFinish', [null, null, {filesCount : 0}]); return; } //endregion const files = Object.values(this.queue.itForUpload.items); const formData = this.getFormData(); //region Here we can change formData const changedData = {}; const buffer1 = { post: {data: changedData, size: 0, filesCount: files.length}, //compatibility field filesCount: files.length, }; const eventOnPackageIsInitialized = new BaseEvent(); eventOnPackageIsInitialized.setCompatData([buffer1, this.queue.itForUpload]); eventOnPackageIsInitialized.setData({ formData: formData, data: changedData, files: files }); EventEmitter.emit(this, 'onPackageIsInitialized', eventOnPackageIsInitialized); appendToForm(formData, buffer1.post.data); if (buffer1.post.data !== changedData) { appendToForm(formData, changedData); } //endregion const packageId = 'pIndex' + (new Date().valueOf() + Math.round(Math.random() * 1000000)); formData.append(this.params["uploadInputInfoName"] + '[packageIndex]', packageId); formData.append(this.params["uploadInputInfoName"] + '[mode]', 'upload'); formData.append(this.params["uploadInputInfoName"] + '[filesCount]', files.length); if (this.packages.size <= 0) { console.group('Upload'); } console.log('1. Create a new Package'); const packItem = new Package({ id: packageId, formData: formData, files: files, uploadFileUrl : this.uploadFileUrl, uploadInputName: this.params["uploadInputName"], }); this.queue.itForUpload = new UploaderUtils.Hash(); const eventOnStart = new BaseEvent(); eventOnStart.setCompatData([packageId, Object.assign( {post: {data: packItem.data, filesCount: files.length}}, packItem), this]); eventOnStart.setData({package: packItem}); EventEmitter.emit(this, 'onStart', eventOnStart); this.packages.set(packItem.getId(), packItem); EventEmitter.emit(this, 'onBusy'); packItem.subscribeOnce('done', ({target: p, data: {status}}) => { const evDone = new BaseEvent(); evDone.setCompatData([{}, packageId, packItem, packItem.getServerResponse()]); evDone.setData({package: packItem, response: packItem.getServerResponse()}); EventEmitter.emit(this, 'onDone', evDone); // region Compatibility if (status === 'failed') { EventEmitter.emit(this, 'onError', new BaseEvent({compatData: [{}, packageId, packItem.getServerResponse()]})); } // endregion Compatibility this.packages.delete(p.getId()); if (this.packages.size <= 0) { setTimeout(() => { const ev = new BaseEvent(); ev.setCompatData([{}, packageId, packItem, packItem.getServerResponse()]); ev.setData({package: packItem, response: packItem.getServerResponse()}); EventEmitter.emit(this, 'onFinish', ev); console.groupEnd('Upload'); }); } }); packItem.subscribe('fileIsUploaded', ({data: {itemId, item, response}}) => { this.queue.itUploaded.setItem(itemId, item); BX.onCustomEvent(this, 'onFileIsUploaded', [itemId, item, response]); BX.onCustomEvent(item, 'onUploadDone', [item, response, this, packItem.getId()]); }); packItem.subscribe('fileIsErrored', ({data: {itemId, item, response}}) => { this.queue.itFailed.setItem(itemId, item); BX.onCustomEvent(this, 'onFileIsUploadedWithError', [itemId, item, response, this, packItem.getId()]); BX.onCustomEvent(item, 'onUploadError', [item, response, this, packItem.getId()]); }); packItem.subscribe('fileIsInProgress', ({data: {item, percent}}) => { BX.onCustomEvent(item, 'onUploadProgress', [item, percent, this, packItem.getId()]); }); if (packItem.prepare()) { files.forEach((item: BX.UploaderFile) => { BX.onCustomEvent(item, 'onUploadStart', [item, 0, this, packItem.getId()]); }); Streams.addPackage(packItem); } } log(text) { } destruct() { EventEmitter.emit(this, Options.getEventName('destroy')); delete this.dropZone; } /*region Compatbility */ get controlID() { return this.controlId; } get dialogName() { return "BX.Uploader"; } get length(): number { return this.queue.itForUpload.length; } get streams() { if (!this['#_streams']) { this['#_streams'] = { packages: { getItem: (id) => { return this.packages.get(id); } } }; } return this['#_streams']; } /*endregion*/ getItem(id) { return this.queue.getItem(id); } getItems() { return this.queue.items; } restoreItems() { //Todo check it this.queue.restoreFiles.apply(this.queue, arguments); } clear() { var item; while((item = this.queue.items.getFirst()) && item) { item.deleteFile(); } } static getById(id) { return this.repo.get(id); } static getInstanceById(id) { return this.repo.get(id); } static getInstance = function(params) { BX.onCustomEvent(window, "onUploaderIsAlmostInited", ['BX.Uploader', params]); return new this(params); } static getInstanceName() { return 'BX.Uploader'; } }