FileStoreController.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. const logger = require('logger-sharelatex')
  2. const FileStoreHandler = require('./FileStoreHandler')
  3. const ProjectLocator = require('../Project/ProjectLocator')
  4. const Errors = require('../Errors/Errors')
  5. module.exports = {
  6. getFile(req, res) {
  7. const projectId = req.params.Project_id
  8. const fileId = req.params.File_id
  9. const queryString = req.query
  10. const userAgent = req.get('User-Agent')
  11. logger.log({ projectId, fileId, queryString }, 'file download')
  12. ProjectLocator.findElement(
  13. { project_id: projectId, element_id: fileId, type: 'file' },
  14. function(err, file) {
  15. if (err) {
  16. logger.err(
  17. { err, projectId, fileId, queryString },
  18. 'error finding element for downloading file'
  19. )
  20. return res.sendStatus(500)
  21. }
  22. FileStoreHandler.getFileStream(projectId, fileId, queryString, function(
  23. err,
  24. stream
  25. ) {
  26. if (err) {
  27. logger.err(
  28. { err, projectId, fileId, queryString },
  29. 'error getting file stream for downloading file'
  30. )
  31. return res.sendStatus(500)
  32. }
  33. // mobile safari will try to render html files, prevent this
  34. if (isMobileSafari(userAgent) && isHtml(file)) {
  35. logger.log(
  36. { filename: file.name, userAgent },
  37. 'sending html file to mobile-safari as plain text'
  38. )
  39. res.setHeader('Content-Type', 'text/plain')
  40. }
  41. res.setContentDisposition('attachment', { filename: file.name })
  42. stream.pipe(res)
  43. })
  44. }
  45. )
  46. },
  47. getFileHead(req, res) {
  48. const projectId = req.params.Project_id
  49. const fileId = req.params.File_id
  50. FileStoreHandler.getFileSize(projectId, fileId, (err, fileSize) => {
  51. if (err) {
  52. if (err instanceof Errors.NotFoundError) {
  53. res.status(404).end()
  54. } else {
  55. logger.err({ err, projectId, fileId }, 'error getting file size')
  56. res.status(500).end()
  57. }
  58. return
  59. }
  60. res.set('Content-Length', fileSize)
  61. res.status(200).end()
  62. })
  63. }
  64. }
  65. function isHtml(file) {
  66. return (
  67. fileEndsWith(file, '.html') ||
  68. fileEndsWith(file, '.htm') ||
  69. fileEndsWith(file, '.xhtml')
  70. )
  71. }
  72. function fileEndsWith(file, ext) {
  73. return (
  74. file.name != null &&
  75. file.name.length > ext.length &&
  76. file.name.lastIndexOf(ext) === file.name.length - ext.length
  77. )
  78. }
  79. function isMobileSafari(userAgent) {
  80. return (
  81. userAgent &&
  82. (userAgent.indexOf('iPhone') >= 0 || userAgent.indexOf('iPad') >= 0)
  83. )
  84. }