forked from OCA/storage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathir_binary.py
147 lines (133 loc) · 4.87 KB
/
ir_binary.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
import werkzeug.http
from odoo import models
from odoo.http import request
from odoo.tools.image import image_process
from ..fs_stream import FsStream
_logger = logging.getLogger(__name__)
class IrBinary(models.AbstractModel):
_inherit = "ir.binary"
def _get_fs_attachment_for_field(self, record, field_name):
if record._name == "ir.attachment" and record.fs_filename:
return record
record.check_field_access_rights("read", [field_name])
field_def = record._fields[field_name]
if field_def.attachment and field_def.store:
fs_attachment = (
self.env["ir.attachment"]
.sudo()
.search(
domain=[
("res_model", "=", record._name),
("res_id", "=", record.id),
("res_field", "=", field_name),
],
limit=1,
)
)
if fs_attachment and fs_attachment.fs_filename:
return fs_attachment
return None
def _record_to_stream(self, record, field_name):
# Extend base implementation to support attachment stored into a
# filesystem storage
fs_attachment = self._get_fs_attachment_for_field(record, field_name)
if fs_attachment:
return FsStream.from_fs_attachment(fs_attachment)
return super()._record_to_stream(record, field_name)
def _get_stream_from(
self,
record,
field_name="raw",
filename=None,
filename_field="name",
mimetype=None,
default_mimetype="application/octet-stream",
):
stream = super()._get_stream_from(
record,
field_name=field_name,
filename=filename,
filename_field=filename_field,
mimetype=mimetype,
default_mimetype=default_mimetype,
)
if stream.type == "fs":
if mimetype:
stream.mimetype = mimetype
if filename:
stream.download_name = filename
elif record and filename_field in record:
stream.download_name = record[filename_field] or stream.download_name
return stream
def _get_image_stream_from(
self,
record,
field_name="raw",
filename=None,
filename_field="name",
mimetype=None,
default_mimetype="image/png",
placeholder=None,
width=0,
height=0,
crop=False,
quality=0,
):
# we need to override this method since if you pass a width or height or
# set crop=True, the stream data must be a bytes object, not a
# file-like object. In the base implementation, the stream data is
# passed to `image_process` method to transform it and this method
# expects a bytes object.
initial_width = width
initial_height = height
initial_crop = crop
if record._name != "ir.attachment" and field_name:
field_def = record._fields[field_name]
if field_def.type in ("fs_image", "fs_file"):
value = record[field_name]
if value:
record = value.attachment
field_name = "raw"
elif field_def.type in ("binary"):
fs_attachment = self._get_fs_attachment_for_field(record, field_name)
if fs_attachment:
record = fs_attachment
field_name = "raw"
stream = super()._get_image_stream_from(
record,
field_name=field_name,
filename=filename,
filename_field=filename_field,
mimetype=mimetype,
default_mimetype=default_mimetype,
placeholder=placeholder,
width=0,
height=0,
crop=False,
quality=quality,
)
modified = werkzeug.http.is_resource_modified(
request.httprequest.environ,
etag=stream.etag,
last_modified=stream.last_modified,
)
if modified and (initial_width or initial_height or initial_crop):
if stream.type == "path":
with open(stream.path, "rb") as file:
stream.type = "data"
stream.path = None
stream.data = file.read()
elif stream.type == "fs":
stream.data = stream.read()
stream.type = "data"
stream.data = image_process(
stream.data,
size=(initial_width, initial_height),
crop=initial_crop,
quality=quality,
)
stream.size = len(stream.data)
return stream