关于 frappe-core-files
面向 Frappe 开发者的文件管理参考技能,适用于处理附件和文件记录。内容包括程序化及 API 操作、存储路径、隐私权限和自定义存储钩子。
主要功能
- 01保存、读取、附加和删除文件
- 02通过 REST API 上传文件
- 03公共与私有文件的访问规则
- 04文件路径和附件字段
- 05自定义存储钩子与配置
适用场景
- 01将生成的文件附加到 Frappe 文档
- 02通过 REST API 上传文档
- 03为敏感附件设置访问规则
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ impertio-studio/ frappe_claude_skill_package --skill frappe-core-files安装后在 Claude Code 中输入/frappe-core-files确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/.gitkeepanti-patterns.mdexamples.md详细介绍
Frappe 文件管理
快速参考
| 操作 | 方法 | 说明 |
|---|---|---|
| 从字节保存文件 | save_file(fname, content, dt, dn) | 返回 File 文档 |
| 从 URL 保存文件 | save_url(file_url, fname, dt, dn) | 根据 URL 创建 File 文档 |
| 读取文件内容 | frappe.get_file(fname) | 返回 [filename, content] |
| 获取文件路径 | get_file_path(file_name) | 解析为绝对路径 |
| 通过 HTTP 上传 | POST /api/method/upload_file | Multipart 表单上传 |
| 删除文件 | frappe.delete_doc("File", name) | 删除文档和文件系统中的文件 |
| 附加打印文件 | frappe.attach_print(dt, dn, print_format) | 返回 {"fname", "fcontent"} |
| 获取缓存文档 | frappe.get_cached_doc("File", name) | 只读,已缓存 |
决策树
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:核心字段
| 字段 | 类型 | 描述 |
|---|---|---|
file_name | Data | 不含路径的文件名 |
file_url | Data | URL 路径(例如,/files/report.pdf) |
file_type | Data | 扩展名(PDF、PNG、DOCX 等) |
is_private | Check | 0 = 公开,1 = 私有 |
is_folder | Check | 文件夹条目为 True |
folder | Link → File | 父文件夹 |
attached_to_doctype | Link → DocType | 父文档类型 |
attached_to_name | Data | 父文档名称 |
attached_to_field | Data | 父文档上的字段名称 |
content_hash | Data | 用于去重的 SHA-256 |
file_size | Int | 大小,单位为字节 |
文件 URL 模式
| 类型 | URL 模式 | 文件系统路径 |
|---|---|---|
| 公开 | /files/{filename} | {site}/public/files/{filename} |
| 私有 | /private/files/{filename} | {site}/private/files/{filename} |
| 远程 | https://... | 不在本地存储 |
| API | /api/method/{path} | 动态生成 |
有效的 URL 前缀:http://、https://、/api/method/、/files/、/private/files/。
对于敏感文档,始终使用 /private/files/。任何知道 URL 的人都可以访问公开文件,包括未通过身份验证的用户。
权限模型
Frappe 文件采用三层权限模型:
- 管理员 — 可不受限制地访问所有文件
- 公开文件(
is_private=0)— 任何知道 URL 的人都可以读取(读取时无需身份验证) - 私有文件(
is_private=1)— 访问者必须满足以下条件之一:- 用户是文件所有者,或
- 用户对该文件拥有明确的共享权限,或
- 用户对
attached_to_doctype/attached_to_name文档拥有读取权限
切勿将敏感数据存储为公开文件。对于包含个人数据、财务记录或机密信息的文档,务必设置 is_private=1。
以编程方式操作文件
从内容保存文件
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"
从 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,
)
读取文件内容
# 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()
直接创建文件文档
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)
生成并附加 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)
通过 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"
响应:
{
"message": {
"name": "FILE-00001",
"file_name": "document.pdf",
"file_url": "/private/files/document.pdf",
"is_private": 1
}
}
文件大小和扩展名限制
**默认最大文件大小:**每个附件 10 MB。
在 site_config.json 中覆盖:
{
"max_file_size": 20971520
}
**每个文档的最大附件数:**通过「自定义表单」→ DocType 上的「最大附件数」字段设置。
以编程方式检查文件大小:
from frappe.utils.file_manager import check_max_file_size
check_max_file_size(content) # raises MaxFileSizeReachedError if too large
附件字段类型
| 字段类型 | 存储内容 | 界面 |
|---|---|---|
Attach | 单个文件 URL | 文件选择器 + 上传按钮 |
Attach Image | 单个图片 URL | 图片预览 + 上传 |
两者都会在字段值中存储 file_url 字符串。File DocType 记录会单独创建,并设置 attached_to_field。
S3 / 云存储集成
Frappe 支持通过 delete_file_data_content hook 和自定义上传处理程序使用自定义文件存储。
通过 frappe-s3-attachment 或类似应用使用 S3
# In hooks.py of custom app
delete_file_data_content = "my_app.storage.delete_from_s3"
使用自定义存储后端时,务必测试文件删除功能——默认的 delete_file_from_filesystem 只处理本地文件。
配置模式
# site_config.json for S3-compatible storage
{
"s3_bucket": "my-frappe-files",
"s3_region": "eu-west-1",
"s3_access_key": "AKIA...",
"s3_secret_key": "...",
}
版本差异
| 特性 | v14 | v15 | v16 |
|---|---|---|---|
| 文件 DocType | 可用 | 可用 | 可用 |
content_hash 去重 | 可用 | 可用 | 可用 |
| 图像优化 | 手动 | 自动(1920x1080,85%) | 自动 |
| Zip 导入/导出 | 不可用 | 可用 | 可用 |
另请参阅
- references/examples.md — 文件操作代码示例
- references/anti-patterns.md — 常见的文件处理错误
frappe-core-permissions— 文件访问权限模型frappe-core-database— File 查询的数据库操作
评论
支持 Markdown