Skip to content

Commit a1f24b5

Browse files
[IMP] dms: Upload file and create dms.file directly
Related to #470 (comment) (cherry picked from commit 938f72d) Co-authored-by: Don Kendall <dkendall@ledoweb.com>
1 parent a884da2 commit a1f24b5

3 files changed

Lines changed: 74 additions & 85 deletions

File tree

dms/controllers/main.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
# Copyright 2017-2019 MuK IT GmbH
2+
# Copyright 2026 Tecnativa - Víctor Martínez
23
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
4+
import json
5+
import unicodedata
6+
37
from odoo import http
8+
from odoo.exceptions import AccessError
49
from odoo.http import request
510

11+
from odoo.addons.web.controllers.binary import clean
12+
613

714
class OnboardingController(http.Controller):
815
@http.route("/config/dms.forbidden_extensions", type="jsonrpc", auth="user")
@@ -13,3 +20,55 @@ def forbidden_extensions(self, **_kwargs):
1320
"dms.forbidden_extensions", default=""
1421
)
1522
}
23+
24+
@http.route("/web/binary/upload_dms_file", type="http", auth="user")
25+
def upload_dms_file(self, ufile, directory_id, callback=None):
26+
"""Similar to the web upload_attachment() method, but customized to
27+
directly create dms.file records.
28+
"""
29+
directory_id = int(directory_id)
30+
files = request.httprequest.files.getlist("ufile")
31+
Model = request.env["dms.file"]
32+
out = """<script language="javascript" type="text/javascript">
33+
var win = window.top.window;
34+
win.jQuery(win).trigger(%s, %s);
35+
</script>"""
36+
args = []
37+
for ufile in files:
38+
filename = ufile.filename
39+
if request.httprequest.user_agent.browser == "safari":
40+
# Safari sends NFD UTF-8 (where é is composed by 'e' and [accent])
41+
# we need to send it the same stuff, otherwise it'll fail
42+
filename = unicodedata.normalize("NFD", ufile.filename)
43+
try:
44+
dms_file = Model.create(
45+
{
46+
"directory_id": directory_id,
47+
"name": filename,
48+
"content_binary": ufile.read(),
49+
}
50+
)
51+
except AccessError:
52+
args.append(
53+
{
54+
"error": request.env._(
55+
"You are not allowed to upload a file here."
56+
)
57+
}
58+
)
59+
except Exception:
60+
args.append({"error": request.env._("Something horrible happened")})
61+
else:
62+
args.append(
63+
{
64+
"filename": clean(filename),
65+
"mimetype": dms_file.mimetype,
66+
"id": dms_file.id,
67+
"size": dms_file.size,
68+
}
69+
)
70+
return (
71+
out % (json.dumps(clean(callback)), json.dumps(args))
72+
if callback
73+
else json.dumps(args)
74+
)

dms/models/dms_file.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -650,29 +650,3 @@ def _compute_locked(self):
650650
)
651651
else:
652652
record.update({"is_locked": False, "is_lock_editor": False})
653-
654-
def get_attachment_object(self, attachment):
655-
return {
656-
"name": attachment.name,
657-
"datas": attachment.datas,
658-
"res_model": attachment.res_model,
659-
"mimetype": attachment.mimetype,
660-
}
661-
662-
@api.model
663-
def get_dms_files_from_attachments(self, attachment_ids=None):
664-
"""Get the dms files from uploaded attachments.
665-
:return: An Array of dms files.
666-
"""
667-
if not attachment_ids:
668-
raise UserError(self.env._("No attachment was provided"))
669-
670-
attachments = self.env["ir.attachment"].browse(attachment_ids)
671-
672-
if any(
673-
attachment.res_id or attachment.res_model != "dms.file"
674-
for attachment in attachments
675-
):
676-
raise UserError(self.env._("Invalid attachments!"))
677-
678-
return [self.get_attachment_object(attachment) for attachment in attachments]

dms/static/src/js/views/dms_file_upload.esm.js

Lines changed: 15 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -80,37 +80,8 @@ export function createFileUploadExtension() {
8080
},
8181

8282
async onChangeFileInput() {
83-
const params = {
84-
csrf_token: odoo.csrf_token,
85-
ufile: [...this.fileInput.el.files],
86-
model: "dms.file",
87-
id: 0,
88-
};
89-
90-
const fileData = await this.http.post(
91-
"/web/binary/upload_attachment",
92-
params,
93-
"text"
94-
);
95-
const attachments = JSON.parse(fileData);
96-
if (attachments.error) {
97-
throw new Error(attachments.error);
98-
}
99-
100-
await this.onUpload(attachments);
101-
},
102-
103-
async onUpload(attachments) {
10483
const self = this;
105-
const attachmentIds = attachments.map((a) => a.id);
106-
const ctx = this.props.context;
10784
const controllerID = this.actionService.currentController.jsId;
108-
109-
if (!attachmentIds.length) {
110-
this.notification.add(_t("An error occurred during the upload"));
111-
return;
112-
}
113-
11485
// Search the correct directory_id value according to the domain
11586
let directory_id = false;
11687
if (this.props.domain) {
@@ -133,37 +104,22 @@ export function createFileUploadExtension() {
133104
});
134105
}
135106

136-
const attachment_datas = await this.orm.call(
137-
"dms.file",
138-
"get_dms_files_from_attachments",
139-
[],
140-
{attachment_ids: attachmentIds}
141-
);
142-
143-
const attachments_args = [];
144-
145-
attachment_datas.forEach((attachment_data) => {
146-
attachments_args.push({
147-
name: attachment_data.name,
148-
content: attachment_data.datas,
149-
mimetype: attachment_data.mimetype,
150-
directory_id,
151-
});
152-
});
107+
const params = {
108+
csrf_token: odoo.csrf_token,
109+
ufile: [...this.fileInput.el.files],
110+
directory_id: directory_id,
111+
};
153112

154-
this.orm
155-
.call("dms.file", "create", [attachments_args], {
156-
context: ctx,
157-
})
158-
.then(() => {
159-
self.actionService.restore(controllerID);
160-
})
161-
.catch((error) => {
162-
self.notification.add(error.data.message, {
163-
type: "danger",
164-
});
165-
self.actionService.restore(controllerID);
166-
});
113+
const fileData = await this.http.post(
114+
"/web/binary/upload_dms_file",
115+
params,
116+
"text"
117+
);
118+
const result = JSON.parse(fileData);
119+
if (result.error) {
120+
throw new Error(result.error);
121+
}
122+
self.actionService.restore(controllerID);
167123
},
168124
};
169125
}

0 commit comments

Comments
 (0)