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.

80 lines
3.3 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
  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. return request.not_found()
  51. try:
  52. last_update = obj['__last_update']
  53. except AccessError:
  54. return wrappers.Response(status=403, headers=[])
  55. status, headers, content = None, [], None
  56. content = obj.with_context({'stream': True})[field] or b''
  57. if not filename:
  58. if filename_field in obj:
  59. filename = obj[filename_field]
  60. else:
  61. filename = "%s-%s-%s" % (obj._name, obj.id, field)
  62. mimetype = 'mimetype' in obj and obj.mimetype or False
  63. if not mimetype and filename:
  64. mimetype = mimetypes.guess_type(filename)[0]
  65. headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')]
  66. etag = bool(request) and request.httprequest.headers.get('If-None-Match')
  67. retag = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest()
  68. status = status or (304 if etag == retag else 200)
  69. headers.append(('ETag', retag))
  70. if download:
  71. headers.append(('Content-Disposition', http.content_disposition(filename)))
  72. return wrappers.Response(content, headers=headers, direct_passthrough=True, status=status)