gridfs/models/File.model.js

  1. /**
  2. * @module flitter-gridfs/models/File
  3. */
  4. const Model = require('flitter-orm/src/model/Model')
  5. const path = require('path')
  6. const fs = require('fs')
  7. const Mongo = require('mongodb')
  8. /**
  9. * Model to represent a stored file.
  10. * @extends {module:flitter-orm/src/model/Model~Model}
  11. */
  12. class GridFile extends Model {
  13. /**
  14. * Defines the services required by this model.
  15. * @returns {Array<string>}
  16. */
  17. static get services() {
  18. return [...super.services, 'gridfs']
  19. }
  20. /**
  21. * Defines the schema used by this model.
  22. * @returns {object}
  23. */
  24. static get schema() {
  25. return {
  26. name: String,
  27. content_type: String,
  28. created_on: {type: Date, default: () => new Date},
  29. file_id: String,
  30. data: {type: String, default: '{}'},
  31. }
  32. }
  33. /**
  34. * Get the GridFS files collection.
  35. * @returns {Promise<mongodb/Collection>}
  36. */
  37. static async files() {
  38. return this.gridfs.mongo_db.collection('fs.files')
  39. }
  40. /**
  41. * Convert an object ID string to a MongoDB ObjectId.
  42. * @param {string} id
  43. * @returns {mongodb/ObjectId}
  44. */
  45. static object_id(id) {
  46. return Mongo.ObjectId(id)
  47. }
  48. /**
  49. * Get a file record by ID string from the grid files collection.
  50. * @param {string} id
  51. * @returns {Promise<object>} - resolves to the retrieved file record object
  52. */
  53. static async one(id) {
  54. const files = await this.files()
  55. return files.findOne({_id: this.object_id(id)})
  56. }
  57. /**
  58. * Get the GridFSBucket used by the model.
  59. * @returns {mongodb/GridFS/Bucket} - the GridFS bucket
  60. */
  61. grid() {
  62. return this.gridfs.mongo_bucket
  63. }
  64. /**
  65. * Save a file to the grid from a local file.
  66. * @param {string} filepath - path of the file to be uploaded
  67. * @param {string} [filename] - name of the file to save, defaults to the model's this.name
  68. * @returns {Promise<void>}
  69. */
  70. write_from_file({filepath, filename}){
  71. const grid = this.grid()
  72. filename = filename ? filename : this.name
  73. filepath = path.resolve(filepath)
  74. return new Promise((resolve, reject) => {
  75. fs.createReadStream(filepath)
  76. .pipe(grid.openUploadStream(filename))
  77. .on('error', (e) => reject(e))
  78. .on('finish', (file) => {
  79. this.file_id = file._id.toString()
  80. this.save().then(resolve)
  81. })
  82. })
  83. }
  84. /**
  85. * Retrieve the model's file from the Grid and store it to the local filesystem.
  86. * @param {string} filepath - path to which the file should be saved
  87. * @returns {Promise<void>}
  88. */
  89. write_to_file({filepath}){
  90. filepath = path.resolve(filepath)
  91. return new Promise((resolve, reject) => {
  92. this.get_read_stream()
  93. .pipe(fs.createWriteStream(filepath))
  94. .on('error', e => reject(e))
  95. .on('finish', () => resolve())
  96. })
  97. }
  98. /**
  99. * Get the read stream for the model's stored Grid file.
  100. * @returns {mongodb/GridFS/GridFSBucketReadStream}
  101. */
  102. get_read_stream(){
  103. const grid = this.grid()
  104. return grid.openDownloadStream(this.constructor.object_id(this.file_id))
  105. }
  106. /**
  107. * Send this model's stored Grid file as data for the specified response.
  108. * @param {express/Response} response - the response to send to
  109. * @returns {boolean | void}
  110. */
  111. send_to_response(response){
  112. const stream = this.get_read_stream()
  113. response.set({
  114. 'Content-Disposition': `inline; filename="${this.name}"`
  115. })
  116. return stream.pipe(response)
  117. }
  118. }
  119. module.exports = exports = GridFile
JAVASCRIPT
Copied!