89 lines
3.2 KiB
Python
89 lines
3.2 KiB
Python
from odoo import models
|
|
import mimetypes
|
|
import base64
|
|
import io
|
|
import zipfile
|
|
|
|
|
|
class IrAttachment(models.Model):
|
|
_inherit = "ir.attachment"
|
|
|
|
def _detect_mimetype(self, datas):
|
|
# direct copy of the above function
|
|
try:
|
|
raw = base64.b64decode(datas)
|
|
except:
|
|
return "application/octet-stream"
|
|
|
|
|
|
# office zip check
|
|
if raw.startswith(b"PK"):
|
|
try:
|
|
z = zipfile.ZipFile(io.BytesIO(raw))
|
|
names = z.namelist()
|
|
|
|
if "ppt/presentation.xml" in names:
|
|
return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
if "word/document.xml" in names:
|
|
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
if "xl/workbook.xml" in names:
|
|
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
return "application/zip"
|
|
except:
|
|
pass
|
|
|
|
if raw.startswith(b"%PDF-"):
|
|
return "application/pdf"
|
|
|
|
return "application/octet-stream"
|
|
|
|
def _get_extension_from_mimetype(self, mimetype):
|
|
mapping = {
|
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
|
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
|
|
"application/pdf": ".pdf",
|
|
"application/zip": ".zip",
|
|
}
|
|
return mapping.get(mimetype, False)
|
|
|
|
def write(self, vals):
|
|
res = super().write(vals)
|
|
|
|
# ----------------------------------------------------
|
|
# 1) Fix incorrect mimetype (ex: .pptx → zip)
|
|
# ----------------------------------------------------
|
|
if "datas" in vals or "mimetype" in vals:
|
|
for rec in self:
|
|
datas = vals.get("datas", rec.datas)
|
|
mimetype = self._detect_mimetype(datas)
|
|
|
|
# Update mimetype if wrong
|
|
if mimetype != rec.mimetype:
|
|
rec.sudo().write({"mimetype": mimetype})
|
|
|
|
# ----------------------------------------------------
|
|
# 2) Fix the filename extension based on correct mimetype
|
|
# ----------------------------------------------------
|
|
# Detect extension from mimetype
|
|
correct_ext = self._get_extension_from_mimetype(mimetype) or ".bin"
|
|
|
|
filename = rec.name or ""
|
|
current_ext = ""
|
|
if "." in filename:
|
|
current_ext = "." + filename.split(".")[-1].lower()
|
|
|
|
# CASE 1: No filename or no extension
|
|
if not filename or "." not in filename:
|
|
new_name = f"{rec.res_field or 'file'}_{rec.id}{correct_ext}"
|
|
rec.sudo().write({"name": new_name})
|
|
|
|
# CASE 2: Wrong extension → Replace it
|
|
elif current_ext != correct_ext:
|
|
base = filename.rsplit(".", 1)[0]
|
|
new_name = f"{base}{correct_ext}"
|
|
rec.sudo().write({"name": new_name})
|
|
|
|
return res
|
|
|