diff --git a/app/routes/tickets.py b/app/routes/tickets.py index 4a0bb25..b570d6b 100644 --- a/app/routes/tickets.py +++ b/app/routes/tickets.py @@ -25,6 +25,29 @@ logger = logging.getLogger(__name__) ALLOWED_EXT = {'png', 'jpg', 'jpeg', 'gif', 'pdf', 'doc', 'docx', 'txt', 'zip', 'log'} +def _resolve_mime_type(att): + """Return a reliable MIME type for an attachment. + + Browsers sometimes send 'application/octet-stream' for images on upload, + and older attachments may have NULL mime_type. Fall back to an + extension-based lookup so images are always served inline correctly. + """ + stored = (att.mime_type or '').lower().strip() + if stored.startswith('image/'): + return stored + ext_map = { + 'png': 'image/png', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', + 'gif': 'image/gif', 'webp': 'image/webp', 'svg': 'image/svg+xml', + 'pdf': 'application/pdf', + 'doc': 'application/msword', + 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'txt': 'text/plain', 'log': 'text/plain', + 'zip': 'application/zip', + } + ext = att.filename.rsplit('.', 1)[-1].lower() if '.' in att.filename else '' + return ext_map.get(ext, stored or 'application/octet-stream') + + def save_attachment(file, ticket_id=None, comment_id=None, uploader_id=None): filename = secure_filename(file.filename) ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else '' @@ -42,6 +65,22 @@ def save_attachment(file, ticket_id=None, comment_id=None, uploader_id=None): ) db.session.add(att) return att + filename = secure_filename(file.filename) + ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else '' + stored_name = f"{uuid.uuid4().hex}.{ext}" + upload_dir = current_app.config['UPLOAD_FOLDER'] + file.save(os.path.join(upload_dir, stored_name)) + att = Attachment( + ticket_id = ticket_id, + comment_id = comment_id, + filename = filename, + stored_name= stored_name, + file_size = os.path.getsize(os.path.join(upload_dir, stored_name)), + mime_type = file.content_type, + uploaded_by= uploader_id, + ) + db.session.add(att) + return att # ─── Dashboard ──────────────────────────────────────────────────────────────── @@ -382,13 +421,14 @@ def download_attachment(att_id): ) abort(403) upload_dir = current_app.config['UPLOAD_FOLDER'] - is_image = (att.mime_type or '').startswith('image/') + mime = _resolve_mime_type(att) + is_image = mime.startswith('image/') return send_from_directory( upload_dir, att.stored_name, - as_attachment = not is_image, # images render inline; other files force-download + as_attachment = not is_image, download_name = att.filename, - mimetype = att.mime_type or None, + mimetype = mime, ) diff --git a/app/templates/tickets/detail.html b/app/templates/tickets/detail.html index b50ff15..74630ac 100644 --- a/app/templates/tickets/detail.html +++ b/app/templates/tickets/detail.html @@ -41,7 +41,9 @@