diff --git a/ui-admin/src/js/common/messages.js b/ui-admin/src/js/common/messages.js index 13b3aa454ab2812760309ba0eb4a0ed934b1e20b..3dbdd2c8f41331a2acab05470a33d0bafb943987 100644 --- a/ui-admin/src/js/common/messages.js +++ b/ui-admin/src/js/common/messages.js @@ -26,6 +26,7 @@ const keys = { AUTHENTICATION_SERVICE_SWITCH_AAI: 'AUTHENTICATION_SERVICE_SWITCH_AAI', AUTO_SHOW_SELECTED: 'AUTO_SHOW_SELECTED', CANCEL: 'CANCEL', + CANNOT_DOWNLOAD: 'CANNOT_DOWNLOAD', CHANGE_SORTING: 'CHANGE_SORTING', CHILDREN: 'CHILDREN', CHOOSE_FILE: 'CHOOSE_FILE', @@ -372,6 +373,7 @@ const messages_en = { [keys.AUTHENTICATION_SERVICE_SWITCH_AAI]: 'SWITCHaai Single Sign On Login Service', [keys.AUTO_SHOW_SELECTED]: 'Scroll to selected node', [keys.CANCEL]: 'Cancel', + [keys.CANNOT_DOWNLOAD]: 'Cannot download more than ${0} bytes.', [keys.CHILDREN]: 'Children', [keys.CHANGE_SORTING]: 'Change sorting', [keys.CHOOSE_FILE]: 'Choose File', diff --git a/ui-admin/src/js/components/database/data-browser/DataBrowser.jsx b/ui-admin/src/js/components/database/data-browser/DataBrowser.jsx index 1af92879bb616bd0a0c28bc20878f2ba80c26765..3a1b572c6ccec833f7d8a994cca840f1fa761a7c 100644 --- a/ui-admin/src/js/components/database/data-browser/DataBrowser.jsx +++ b/ui-admin/src/js/components/database/data-browser/DataBrowser.jsx @@ -15,6 +15,9 @@ import InfoBar from '@src/js/components/database/data-browser/InfoBar.jsx' import LoadingDialog from '@src/js/components/common/loading/LoadingDialog.jsx' import ErrorDialog from '@src/js/components/common/error/ErrorDialog.jsx' +// 2GB limit for total download size +const sizeLimit = 2147483648 + const styles = theme => ({ columnFlexContainer: { flexDirection: 'column', @@ -316,10 +319,26 @@ class DataBrowser extends React.Component { const { multiselectedFiles } = this.state const { id } = this.props - // TODO: implement download by chunks - const zipBlob = await this.prepareZipBlob(multiselectedFiles) - this.downloadBlob(zipBlob, id) - this.zip = new JSZip() + if ((await this.calculateTotalSize(multiselectedFiles)) <= sizeLimit) { + const zipBlob = await this.prepareZipBlob(multiselectedFiles) + this.downloadBlob(zipBlob, id) + this.zip = new JSZip() + } else { + this.showDownloadErrorDialog() + } + } + + async calculateTotalSize(files) { + let size = 0 + for (let file of files) { + if (!file.directory) { + size += file.size + } else { + const nestedFiles = await this.controller.listFiles(file.path) + size += await this.calculateTotalSize(nestedFiles) + } + } + return size } async prepareZipBlob(files) { @@ -340,15 +359,23 @@ class DataBrowser extends React.Component { } async downloadFile(file) { - try { - this.setState({ loading: true, progress: 0 }) - const blob = await this.fileToBlob(file) - this.downloadBlob(blob, file.name) - } finally { - this.setState({ loading: false, progress: 0 }) + if (file.size <= sizeLimit) { + try { + this.setState({ loading: true, progress: 0 }) + const blob = await this.fileToBlob(file) + this.downloadBlob(blob, file.name) + } finally { + this.setState({ loading: false, progress: 0 }) + } + } else { + this.showDownloadErrorDialog() } } + showDownloadErrorDialog() { + this.openErrorDialog(messages.get(messages.CANNOT_DOWNLOAD, sizeLimit)) + } + updateProgress(progress) { this.setState({ progress }) } @@ -464,7 +491,7 @@ class DataBrowser extends React.Component { errorMessage } = this.state - return ([ + return [ <div className={[classes.boundary, classes.columnFlexContainer].join(' ')} > @@ -596,11 +623,18 @@ class DataBrowser extends React.Component { )} </div> </div>, - <LoadingDialog key='data-browser-loaging-dialog' variant='determinate' - value={progress} loading={loading} />, - <ErrorDialog open={!!errorMessage} error={errorMessage} - onClose={this.closeErrorDialog} /> - ]) + <LoadingDialog + key='data-browser-loaging-dialog' + variant='determinate' + value={progress} + loading={loading} + />, + <ErrorDialog + open={!!errorMessage} + error={errorMessage} + onClose={this.closeErrorDialog} + /> + ] } }