Frappe core files
Skill Impertio-Studio/Frappe_Claude_Skill_Package/skills/source/core/frappe-core-files
60 deterministic Claude AI skills for Frappe Framework & ERPNext v14-v16 development and operations
npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-core-filesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
What its author says it does
Copied from the file, not written here
Use when handling file uploads, attachments, private/public file access, or S3 storage configuration. Prevents broken file URLs, permission leaks on private files, and failed uploads from incorrect MIME handling. Covers File DocType, frappe.get_file, upload API, private vs public directories, S3 integration, file URL patterns, attach field types. Keywords: file, upload, attachment, File DocType, private, public, S3, file_url, get_file, attach, upload not working, file missing, broken file link, download file, image not showing, attachment error..
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.6 KB, as published. Nobody here has run it
Frappe File Management
Quick Reference
| Action | Method | Notes |
|---|---|---|
| Save file from bytes | save_file(fname, content, dt, dn) | Returns File doc |
| Save file from URL | save_url(file_url, fname, dt, dn) | Creates File doc from URL |
| Read file content | frappe.get_file(fname) | Returns [filename, content] |
| Get file path | get_file_path(file_name) | Resolves to absolute path |
| Upload via HTTP | POST /api/method/upload_file | Multipart form upload |
| Delete file | frappe.delete_doc("File", name) | Removes doc + filesystem file |
| Attach print | frappe.attach_print(dt, dn, print_format) | Returns {"fname", "fcontent"} |
| Get cached doc | frappe.get_cached_doc("File", name) | Read-only, cached |
Decision Tree
What file operation do you need?
│
├─ Upload a file from user input?
│ ├─ Via web form → Attach field type (auto-handles upload)
│ └─ Via API → POST /api/method/upload_file
│
├─ Create a file programmatically?
│ ├─ From bytes/content → save_file(fname, content, dt, dn)
│ ├─ From external URL → save_url(file_url, fname, dt, dn)
│ └─ Full control → frappe.get_doc({"doctype": "File", ...}).insert()
│
├─ Read file content?
│ ├─ By filename → frappe.get_file(fname)
│ └─ By File doc → file_doc.get_content()
│
├─ Public or private?
│ ├─ Public (anyone with link) → is_private=0, URL: /files/fname
│ └─ Private (permission-based) → is_private=1, URL: /private/files/fname
│
└─ Generate PDF attachment?
└─ frappe.attach_print(doctype, name, print_format)
File DocType: Core Fields
| Field | Type | Description |
|---|---|---|
file_name | Data | Filename without path |
file_url | Data | URL path (e.g., /files/report.pdf) |
file_type | Data | Extension (PDF, PNG, DOCX, etc.) |
is_private | Check | 0 = public, 1 = private |
is_folder | Check | True for folder entries |
folder | Link → File | Parent folder |
attached_to_doctype | Link → DocType | Parent document type |
attached_to_name | Data | Parent document name |
attached_to_field | Data | Field name on parent |
content_hash | Data | SHA-256 for deduplication |
file_size | Int | Size in bytes |
File URL Patterns
| Type | URL Pattern | Filesystem Path |
|---|---|---|
| Public | /files/{filename} | {site}/public/files/{filename} |
| Private | /private/files/{filename} | {site}/private/files/{filename} |
| Remote | https://... | Not stored locally |
| API | /api/method/{path} | Generated dynamically |
Valid URL prefixes: http://, https://, /api/method/, /files/, /private/files/.
ALWAYS use /private/files/ for sensitive documents. Public files are accessible to anyone with the URL, including unauthenticated users.
Permission Model
Frappe files use a three-tier permission model:
- Administrator — unrestricted access to all files
- Public files (
is_private=0) — readable by anyone with the URL (no authentication required for read) - Private files (
is_private=1) — access requires:- User is the file owner, OR
- User has explicit share on the file, OR
- User has read permission on the
attached_to_doctype/attached_to_namedocument
NEVER store sensitive data as public files. ALWAYS set is_private=1 for documents containing personal data, financial records, or confidential information.
Programmatic File Operations
Save File from Content
from frappe.utils.file_manager import save_file
# Save a generated CSV
csv_content = "Name,Amount\nACME,1000\nGlobex,2000"
file_doc = save_file(
fname="report.csv",
content=csv_content.encode("utf-8"),
dt="Sales Invoice", # attach to this DocType
dn="SINV-00001", # attach to this document
folder="Home/Attachments", # optional folder
is_private=1, # private file
)
# file_doc.file_url → "/private/files/report.csv"
Save File from URL
from frappe.utils.file_manager import save_url
file_doc = save_url(
file_url="https://example.com/logo.png",
filename="company-logo.png",
dt="Company",
dn="My Company",
folder="Home",
is_private=0,
)
Read File Content
# By filename
filename, content = frappe.get_file("report.csv")
# By File document
file_doc = frappe.get_doc("File", {"file_name": "report.csv"})
content_bytes = file_doc.get_content()
Create File Document Directly
file_doc = frappe.get_doc({
"doctype": "File",
"file_name": "generated-report.pdf",
"attached_to_doctype": "Sales Invoice",
"attached_to_name": "SINV-00001",
"is_private": 1,
"content": pdf_bytes, # raw bytes — written to disk on insert
}).insert(ignore_permissions=True)
Generate and Attach PDF
# Create PDF attachment dict (for use with sendmail)
pdf_attachment = frappe.attach_print(
"Sales Invoice",
"SINV-00001",
print_format="Standard",
)
# Returns: {"fname": "Sales Invoice - SINV-00001.pdf", "fcontent": <bytes>}
# Save PDF as file attachment
from frappe.utils.file_manager import save_file
pdf = frappe.get_print("Sales Invoice", "SINV-00001", print_format="Standard", as_pdf=True)
save_file("invoice.pdf", pdf, "Sales Invoice", "SINV-00001", is_private=1)
File Upload via REST API
# Upload file attached to a document
curl -X POST https://site.example.com/api/method/upload_file \
-H "Authorization: token api_key:api_secret" \
-F "file=@/path/to/document.pdf" \
-F "doctype=Sales Invoice" \
-F "docname=SINV-00001" \
-F "is_private=1"
Response:
{
"message": {
"name": "FILE-00001",
"file_name": "document.pdf",
"file_url": "/private/files/document.pdf",
"is_private": 1
}
}
File Size and Extension Limits
Default max file size: 10 MB per attachment.
Override in site_config.json:
{
"max_file_size": 20971520
}
Max attachments per document: Set via Customize Form → Max Attachments field on the DocType.
Check file size programmatically:
from frappe.utils.file_manager import check_max_file_size
check_max_file_size(content) # raises MaxFileSizeReachedError if too large
Attach Field Types
| Field Type | Stores | UI |
|---|---|---|
Attach | Single file URL | File picker + upload button |
Attach Image | Single image URL | Image preview + upload |
Both store the file_url string in the field value. The File DocType record is created separately with attached_to_field set.
S3 / Cloud Storage Integration
Frappe supports custom file storage via the delete_file_data_content hook and custom upload handlers.
S3 via frappe-s3-attachment or similar app
# In hooks.py of custom app
delete_file_data_content = "my_app.storage.delete_from_s3"
ALWAYS test file deletion when using custom storage backends — the default delete_file_from_filesystem only handles local files.
Configuration Pattern
# site_config.json for S3-compatible storage
{
"s3_bucket": "my-frappe-files",
"s3_region": "eu-west-1",
"s3_access_key": "AKIA...",
"s3_secret_key": "...",
}
Version Differences
| Feature | v14 | v15 | v16 |
|---|---|---|---|
| File DocType | Available | Available | Available |
content_hash dedup | Available | Available | Available |
| Image optimization | Manual | Auto (1920x1080, 85%) | Auto |
| Import/Export Zip | Not available | Available | Available |
See Also
- references/examples.md — File operation code examples
- references/anti-patterns.md — Common file handling mistakes
frappe-core-permissions— Permission model for file accessfrappe-core-database— Database operations for File queries