diff --git a/models/lib/fileStoreStrategy.js b/models/lib/fileStoreStrategy.js index b49c894e3..22c9cbf18 100644 --- a/models/lib/fileStoreStrategy.js +++ b/models/lib/fileStoreStrategy.js @@ -1,6 +1,6 @@ import fs from 'fs'; import { createObjectId } from './grid/createObjectId'; -import { createInterceptDownload } from './fsHooks/createInterceptDownload'; +import { httpStreamOutput } from './httpStream.js' export const STORAGE_NAME_FILESYSTEM = "fs"; export const STORAGE_NAME_GRIDFS = "gridfs"; @@ -125,7 +125,15 @@ export class FileStoreStrategyGridFs extends FileStoreStrategy { * @param http the current http request */ interceptDownload(http) { - const ret = createInterceptDownload(this.filesCollection, this.gridFsBucket, this.fileObj, http, this.versionName); + const readStream = this.getReadStream(); + const downloadFlag = http?.params?.query?.download; + + let ret = false; + if (readStream) { + ret = true; + httpStreamOutput(readStream, this.fileObj.name, http, downloadFlag, this.filesCollection.cacheControl); + } + return ret; } @@ -195,15 +203,23 @@ export class FileStoreStrategyGridFs extends FileStoreStrategy { * @return the GridFS Object-Id */ getGridFsObjectId() { - const gridFsFileId = (this.fileObj.versions[this.versionName].meta || {}) - .gridFsFileId; let ret; + const gridFsFileId = this.getGridFsFileId(); if (gridFsFileId) { ret = createObjectId({ gridFsFileId }); } return ret; } + /** returns the GridFS Object-Id + * @return the GridFS Object-Id + */ + getGridFsFileId() { + const ret = (this.fileObj.versions[this.versionName].meta || {}) + .gridFsFileId; + return ret; + } + /** returns the property name of gridFsFileId * @return the property name of gridFsFileId */ diff --git a/models/lib/fsHooks/createInterceptDownload.js b/models/lib/fsHooks/createInterceptDownload.js deleted file mode 100644 index 1d094c3f9..000000000 --- a/models/lib/fsHooks/createInterceptDownload.js +++ /dev/null @@ -1,47 +0,0 @@ -import { createObjectId } from '../grid/createObjectId'; - -export const createInterceptDownload = - function interceptDownload(filesCollection, bucket, file, http, versionName) { - const { gridFsFileId } = file.versions[versionName].meta || {}; - if (gridFsFileId) { - // opens the download stream using a given gfs id - // see: http://mongodb.github.io/node-mongodb-native/3.2/api/GridFSBucket.html#openDownloadStream - const gfsId = createObjectId({ gridFsFileId }); - const readStream = bucket.openDownloadStream(gfsId); - - readStream.on('data', data => { - http.response.write(data); - }); - - readStream.on('end', () => { - http.response.end(); // don't pass parameters to end() or it will be attached to the file's binary stream - }); - - readStream.on('error', () => { - // not found probably - // eslint-disable-next-line no-param-reassign - http.response.statusCode = 404; - http.response.end('not found'); - }); - - http.response.setHeader('Cache-Control', filesCollection.cacheControl); - http.response.setHeader( - 'Content-Disposition', - getContentDisposition(file.name, http?.params?.query?.download), - ); - } - return Boolean(gridFsFileId); // Serve file from either GridFS or FS if it wasn't uploaded yet - }; - -/** - * Will initiate download, if links are called with ?download="true" queryparam. - **/ -const getContentDisposition = (name, downloadFlag) => { - const dispositionType = downloadFlag === 'true' ? 'attachment;' : 'inline;'; - - const encodedName = encodeURIComponent(name); - const dispositionName = `filename="${encodedName}"; filename=*UTF-8"${encodedName}";`; - const dispositionEncoding = 'charset=utf-8'; - - return `${dispositionType} ${dispositionName} ${dispositionEncoding}`; -}; diff --git a/models/lib/httpStream.js b/models/lib/httpStream.js new file mode 100644 index 000000000..953d83134 --- /dev/null +++ b/models/lib/httpStream.js @@ -0,0 +1,29 @@ +export const httpStreamOutput = function(readStream, name, http, downloadFlag, cacheControl) { + readStream.on('data', data => { + http.response.write(data); + }); + + readStream.on('end', () => { + // don't pass parameters to end() or it will be attached to the file's binary stream + http.response.end(); + }); + + readStream.on('error', () => { + http.response.statusCode = 404; + http.response.end('not found'); + }); + + http.response.setHeader('Cache-Control', cacheControl); + http.response.setHeader('Content-Disposition', getContentDisposition(name, http?.params?.query?.download)); + }; + +/** will initiate download, if links are called with ?download="true" queryparam */ +const getContentDisposition = (name, downloadFlag) => { + const dispositionType = downloadFlag === 'true' ? 'attachment;' : 'inline;'; + + const encodedName = encodeURIComponent(name); + const dispositionName = `filename="${encodedName}"; filename=*UTF-8"${encodedName}";`; + const dispositionEncoding = 'charset=utf-8'; + + return `${dispositionType} ${dispositionName} ${dispositionEncoding}`; +};