You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
4.1 KiB

  1. ###################################################################################
  2. #
  3. # Copyright (C) 2018 MuK IT GmbH
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU Affero General Public License as
  7. # published by the Free Software Foundation, either version 3 of the
  8. # License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU Affero General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Affero General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. #
  18. ###################################################################################
  19. import logging
  20. import mimetypes
  21. from odoo import models
  22. from odoo.http import request, STATIC_CACHE
  23. from odoo.exceptions import AccessError
  24. _logger = logging.getLogger(__name__)
  25. class LargeObjectControllerIrHttp(models.AbstractModel):
  26. _inherit = 'ir.http'
  27. @classmethod
  28. def lobject_content(cls, xmlid=None, model=None, id=None, field='content', unique=False,
  29. filename=None, filename_field='content_fname', download=False,
  30. mimetype=None, default_mimetype='application/octet-stream', env=None):
  31. """ Get file, attachment or downloadable content
  32. If the xmlid and id parameter is omitted, fetches the default value for the
  33. binary field (via the default_get method), otherwise fetches the field for
  34. that precise record.
  35. :param str xmlid: xmlid of the record
  36. :param str model: name of the model to fetch the binary from
  37. :param int id: id of the record from which to fetch the binary
  38. :param str field: binary field
  39. :param bool unique: add a max-age for the cache control
  40. :param str filename: choose a filename
  41. :param str filename_field: if not create an filename with model-id-field
  42. :param bool download: apply headers to download the file
  43. :param str mimetype: mintype of the field (for headers)
  44. :param str default_mimetype: default mintype if no mintype found
  45. :param Environment env: by default use request.env
  46. :returns: (status, headers, content)
  47. """
  48. obj = None
  49. env = env or request.env
  50. if xmlid:
  51. obj = cls._xmlid_to_obj(env, xmlid)
  52. elif id and model in env.registry:
  53. obj = env[model].browse(int(id))
  54. if not obj or not obj.exists() or field not in obj:
  55. return (404, [], None)
  56. try:
  57. last_update = obj['__last_update']
  58. except AccessError:
  59. return (403, [], None)
  60. status, headers, content = None, [], None
  61. content = obj.with_context({'stream': True})[field] or b''
  62. if not filename:
  63. if filename_field in obj:
  64. filename = obj[filename_field]
  65. else:
  66. filename = "%s-%s-%s" % (obj._name, obj.id, field)
  67. mimetype = 'mimetype' in obj and obj.mimetype or False
  68. if not mimetype and filename:
  69. mimetype = mimetypes.guess_type(filename)[0]
  70. if not mimetype:
  71. mimetype = default_mimetype
  72. headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]
  73. etag = bool(request) and request.httprequest.headers.get('If-None-Match')
  74. retag = '"%s"' % obj.with_context({'checksum': True})[field] if content else ""
  75. status = status or (304 if etag == retag else 200)
  76. headers.append(('ETag', retag))
  77. headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))
  78. if download:
  79. headers.append(('Content-Disposition', cls.content_disposition(filename)))
  80. return (status, headers, content)