diff --git a/src/components/fileupload/FileUpload.d.ts b/src/components/fileupload/FileUpload.d.ts index 755124eb3..ae0255cf8 100755 --- a/src/components/fileupload/FileUpload.d.ts +++ b/src/components/fileupload/FileUpload.d.ts @@ -10,11 +10,14 @@ export declare class FileUpload extends Vue { auto?: boolean; maxFileSize?: number; invalidFileSizeMessage?: string; + invalidFileLimitMessage?: string; + fileLimit?: number; withCredentials?: boolean; previewWidth?: number; chooseLabel?: string; uploadLabel?: string; cancelLabel?: string; + customUpload?: boolean; $emit(eventName: 'select', e: { originalEvent: Event, files: any }): this; $emit(eventName: 'before-upload', e: { xhr: XMLHttpRequest, formData: any }): this; $emit(eventName: 'progress', e: { originalEvent: Event, progress: any }): this; diff --git a/src/components/fileupload/FileUpload.vue b/src/components/fileupload/FileUpload.vue index 1a844a7d2..ea2d025ed 100755 --- a/src/components/fileupload/FileUpload.vue +++ b/src/components/fileupload/FileUpload.vue @@ -2,12 +2,12 @@
- + {{chooseLabel}} - - + +
@@ -84,6 +84,14 @@ export default { type: String, default: '{0}: Invalid file size, file size should be smaller than {1}.' }, + fileLimit: { + type: Number, + default: null + }, + invalidFileLimitMessage: { + type: String, + default: 'Maximum number of files exceeded, limit is {0} at most.' + }, withCredentials: { type: Boolean, default: false @@ -103,9 +111,14 @@ export default { cancelLabel: { type: String, default: 'Cancel' + }, + customUpload: { + type: Boolean, + default: false } }, duplicateIEEvent: false, + uploadedFileCount: 0, data() { return { files: null, @@ -137,7 +150,11 @@ export default { this.$emit('select', {originalEvent: event, files: files}); - if (this.auto && this.hasFiles) { + if (this.fileLimit) { + this.checkFileLimit(); + } + + if (this.auto && this.hasFiles && !this.isFileLimitExceeded()) { this.upload(); } @@ -152,60 +169,73 @@ export default { this.$refs.fileInput.click(); }, upload() { - let xhr = new XMLHttpRequest(); - let formData = new FormData(); + if (this.customUpload) { + if (this.fileLimit) { + this.uploadedFileCount += this.files.length; + } - this.$emit('before-upload', { - 'xhr': xhr, - 'formData': formData - }); - - for (let file of this.files) { - formData.append(this.name, file, file.name); + this.$emit('uploader', {files: this.files}); } + else { + let xhr = new XMLHttpRequest(); + let formData = new FormData(); - xhr.upload.addEventListener('progress', (event) => { - if (event.lengthComputable) { - this.progress = Math.round((event.loaded * 100) / event.total); - } - - this.$emit('progress', { - originalEvent: event, - progress: this.progress + this.$emit('before-upload', { + 'xhr': xhr, + 'formData': formData }); - }); - xhr.onreadystatechange = () => { - if (xhr.readyState === 4) { - this.progress = 0; - - if (xhr.status >= 200 && xhr.status < 300) { - this.$emit('upload', { - xhr: xhr, - files: this.files - }); - } - else { - this.$emit('error', { - xhr: xhr, - files: this.files - }); - } - - this.clear(); + for (let file of this.files) { + formData.append(this.name, file, file.name); } - }; - xhr.open('POST', this.url, true); + xhr.upload.addEventListener('progress', (event) => { + if (event.lengthComputable) { + this.progress = Math.round((event.loaded * 100) / event.total); + } - this.$emit('before-send', { - 'xhr': xhr, - 'formData': formData - }); + this.$emit('progress', { + originalEvent: event, + progress: this.progress + }); + }); - xhr.withCredentials = this.withCredentials; + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + this.progress = 0; - xhr.send(formData); + if (xhr.status >= 200 && xhr.status < 300) { + if (this.fileLimit) { + this.uploadedFileCount += this.files.length; + } + + this.$emit('upload', { + xhr: xhr, + files: this.files + }); + } + else { + this.$emit('error', { + xhr: xhr, + files: this.files + }); + } + + this.clear(); + } + }; + + xhr.open('POST', this.url, true); + + this.$emit('before-send', { + 'xhr': xhr, + 'formData': formData + }); + + xhr.withCredentials = this.withCredentials; + + xhr.send(formData); + } }, clear() { this.files = null; @@ -308,6 +338,22 @@ export default { i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; + }, + isFileLimitExceeded() { + if (this.fileLimit && this.fileLimit <= this.files.length + this.uploadedFileCount && this.focused) { + this.focused = false; + } + + return this.fileLimit && this.fileLimit < this.files.length + this.uploadedFileCount; + }, + checkFileLimit() { + if (this.isFileLimitExceeded()) { + this.msgs.push({ + severity: 'error', + summary: this.invalidFileLimitMessageSummary.replace('{0}', this.fileLimit.toString()), + detail: this.invalidFileLimitMessageDetail.replace('{0}', this.fileLimit.toString()) + }); + } } }, computed: { @@ -342,6 +388,15 @@ export default { }, hasFiles() { return this.files && this.files.length > 0; + }, + chooseDisabled() { + return this.disabled || (this.fileLimit && this.fileLimit <= this.files.length + this.uploadedFileCount); + }, + uploadDisabled() { + return this.disabled || !this.hasFiles; + }, + cancelDisabled() { + return this.disabled || !this.hasFiles; } }, components: { diff --git a/src/views/fileupload/FileUploadDoc.vue b/src/views/fileupload/FileUploadDoc.vue index 941c7e29a..adfa74260 100755 --- a/src/views/fileupload/FileUploadDoc.vue +++ b/src/views/fileupload/FileUploadDoc.vue @@ -40,22 +40,37 @@ import FileUpload from 'primevue/fileupload'; <FileUpload mode="basic" name="demo[]" url="./upload" accept="image/*" /> -
File Size
-

Maximium file size can be restricted using maxFileSize property defined in bytes.

+
File Size and File Linit
+

Maximium file size can be restricted using maxFileSize property defined in bytes. Similarly fileLimit is available to restrict the number of files to be uploaded.

-<FileUpload name="demo[]" url="./upload" :maxFileSize="1000000" /> +<FileUpload name="demo[]" url="./upload" :maxFileSize="1000000" :fileLimit="3" /> -

In order to customize the default messages use invalidFileSizeMessage option. In messages, {0} placeholder refers to the filename and in detail message, the file size.

+

In order to customize the default messages use invalidFileSizeMessage and invalidFileLimitMessage options where {0} placeholder refers to the filename and {1} the file size.

  • - invalidFileSizeMessage: '{0}: Invalid file size, file size should be smaller than {1}.' + invalidFileSizeMessage: '{0}: Invalid file size, file size should be smaller than {1}.' +
  • +
  • + invalidFileLimitMessage: 'Maximum number of files exceeded, limit is {0} at most.'
Request Customization

XHR request to upload the files can be customized using the before-upload callback that passes the xhr instance and FormData object as event parameters.

+
Custom Upload
+

Uploading implementation can be overridden by enabling customMode property and defining a custom upload handler event.

+ +<FileUpload name="demo[]" :customUpload="true" @uploader="myUploader" /> + + + +myUploader(event) { + //event.files == files to upload +} + +
Empty Template

When there is no file selected, you may use the empty slot to display content.

@@ -130,7 +145,19 @@ import FileUpload from 'primevue/fileupload'; invalidFileSizeMessage string "{0}: Invalid file size, file size should be smaller than {1}." - Summary message of the invalid fize size. + Message of the invalid fize size. + + + invalidFileLimitMessage + string + Maximum number of files exceeded, limit is {0} at most. + Message to display when number of files to be uploaded exceeeds the limit. + + + fileLimit + number + null + Maximum number of files that can be uploaded. withCredentials @@ -161,6 +188,12 @@ import FileUpload from 'primevue/fileupload'; string Cancel Label of the cancel button. + + + customUpload + boolean + false + Whether to use the default upload or a manual implementation defined in uploadHandler callback. @@ -220,6 +253,11 @@ import FileUpload from 'primevue/fileupload'; event.progress: Calculated progress value. Callback to invoke when files are selected. + + uploader + event.files: List of selected files. + Callback to invoke to implement a custom upload. +