The following code works fine in a doctype but not in a web form. This is because the attached_to_doctype and attached_to_field values are not populated when uploading through the web form.
def validate_file_type(doc, method):
if doc.attached_to_doctype == 'Test Form':
if doc.attached_to_field in ["photograph", "signature"]:
if not doc.file_name.lower().endswith(".jpg") or not doc.file_name.lower().endswith(".jpeg"):
frappe.throw("Only <b>JPG/JPEG</b> file Allowed")
else:
if not doc.file_name.lower().endswith(".pdf"):
frappe.throw("Only <b>PDF</b> file Allowed")
Requirement:
For fields like photograph and signature, the uploaded file should always be in JPG/JPEG format.
For all other attach fields, only PDF files should be allowed.
How can I achieve this validation for my web form where attached_to_doctype and attached_to_field are not available during file upload?
import mimetypes
import frappe
from frappe import _
from frappe.core.doctype.file.exceptions import MaxFileSizeReachedError
from frappe.core.doctype.file.file import File
class CustomFile(File):
def check_max_file_size(self):
# Predefined file size limits by category (in bytes)
file_type_limits = {
"image": 5 * 1024 * 1024, # 5 MB for image files
"document": 10 * 1024 * 1024, # 10 MB for document files
"video": 30 * 1024 * 1024, # 30 MB for video files
}
# Guess the MIME type of the file
file_type = mimetypes.guess_type(self.file_name)[0]
if not file_type:
# If MIME type is undetectable, raise an error
frappe.throw(_("Could not determine file type from MIME type."))
# Determine the file's category based on MIME type
if file_type.startswith("image"):
file_category = "image"
elif file_type.startswith("application"):
# Check for common document types
if any(file_type.startswith(prefix) for prefix in [
"application/pdf",
"application/msword",
"application/vnd.ms-excel",]):
file_category = "document"
elif file_type.startswith("video"):
file_category = "video"
else:
# If file type is unsupported, raise an error
frappe.throw(_("Unsupported file type detected: {0}").format(file_type))
# Get the file content size in bytes
file_size = len(self.get("content") or b"") # Default to empty byte string if no content
# Check if the file size exceeds the maximum allowed limit for the detected category
if file_category and file_size > file_type_limits.get(file_category, 0):
# Raise error if file exceeds limit
max_size_mb = file_type_limits[file_category] / (1024 * 1024) # Convert bytes to MB
msg = _("File size exceeds the maximum allowed limit of {0} MB").format(max_size_mb)
frappe.throw(msg, exc=MaxFileSizeReachedError)
return file_size # Return the file size if it's within limits