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.

83 lines
3.5 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. # -*- coding: utf-8 -*-
  2. ###################################################################################
  3. #
  4. # Copyright (C) 2018 MuK IT GmbH
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Affero General Public License as
  8. # published by the Free Software Foundation, either version 3 of the
  9. # License, or (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Affero General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Affero General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. ###################################################################################
  20. import base64
  21. import logging
  22. import hashlib
  23. import mimetypes
  24. from werkzeug import utils
  25. from werkzeug import wrappers
  26. from odoo import _
  27. from odoo import tools
  28. from odoo import http
  29. from odoo.http import request
  30. from odoo.http import Response
  31. from odoo.tools import pycompat
  32. from odoo.exceptions import AccessError
  33. _logger = logging.getLogger(__name__)
  34. class LargeObjectController(http.Controller):
  35. @http.route(['/web/lobject',
  36. '/web/lobject/<string:xmlid>',
  37. '/web/lobject/<string:xmlid>/<string:filename>',
  38. '/web/lobject/<int:id>',
  39. '/web/lobject/<int:id>/<string:filename>',
  40. '/web/lobject/<string:model>/<int:id>/<string:field>',
  41. '/web/lobject/<string:model>/<int:id>/<string:field>/<string:filename>'], type='http', auth="public")
  42. def content_lobject(self, xmlid=None, model='ir.attachment', id=None, field='datas', filename=None,
  43. filename_field='datas_fname', mimetype=None, download=None, access_token=None):
  44. obj = None
  45. if xmlid:
  46. obj = request.env.ref(xmlid, False)
  47. elif id and model in request.env.registry:
  48. obj = request.env[model].browse(int(id))
  49. if not obj or not obj.exists() or field not in obj:
  50. _logger.info(str(not obj))
  51. _logger.info(str(not obj.exists()))
  52. _logger.info(str(field not in obj))
  53. return request.not_found()
  54. try:
  55. last_update = obj['__last_update']
  56. except AccessError:
  57. return wrappers.Response(status=403, headers=[])
  58. status, headers, content = None, [], None
  59. content = obj.with_context({'stream': True})[field] or b''
  60. if not filename:
  61. if filename_field in obj:
  62. filename = obj[filename_field]
  63. else:
  64. filename = "%s-%s-%s" % (obj._name, obj.id, field)
  65. mimetype = 'mimetype' in obj and obj.mimetype or False
  66. if not mimetype and filename:
  67. mimetype = mimetypes.guess_type(filename)[0]
  68. headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]
  69. etag = bool(request) and request.httprequest.headers.get('If-None-Match')
  70. retag = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest()
  71. status = status or (304 if etag == retag else 200)
  72. headers.append(('ETag', retag))
  73. if download:
  74. headers.append(('Content-Disposition', http.content_disposition(filename)))
  75. return wrappers.Response(content, headers=headers, direct_passthrough=True, status=status)