Ok.
So I figured it out myself, after a timely hint from @revant_one .
I started with a File Manager
like this …
… an Attachments
subsection like this …
… a Sales Invoice
like this …
… and files directories looking like this …
private
├── backups
└── files
├── UOM.csv
└── docType_Chart_of_Accounts_Importer.csv
public
└── files
I execute this script …
# sudo apt install jq;
export PRTCL="http";
export HOST="your.host";
export ERP_KEY="2604a8329cb8834";
export ERP_SCT="4a5e6872df8c5c7";
export DOCTYPE="Sales Invoice";
export DOCID="ACC-SINV-2020-00001";
export THEFILE="Trump-Sad-Pig.jpg";
export FILEDATA=$(base64 -w 0 ${THEFILE});
curl -s -X POST "${PRTCL}://${HOST}/api/method/frappe.client.attach_file" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: token ${ERP_KEY}:${ERP_SCT}" \
--data-urlencode "filename=${THEFILE}" \
--data-urlencode "filedata=${FILEDATA}" \
--data-urlencode "doctype=${DOCTYPE}" \
--data-urlencode "docname=${DOCID}" \
--data-urlencode "is_private=1" \
--data-urlencode "decode_base64=1" \
| jq -r .;
… and get the following response …
{
"message": {
"name": "641967bdb5",
"owner": "Administrator",
"creation": "2020-05-03 09:19:30.788658",
"modified": "2020-05-03 09:19:30.788658",
"modified_by": "Administrator",
"parent": null,
"parentfield": null,
"parenttype": null,
"idx": 0,
"docstatus": 0,
"file_name": "Trump-Sad-Pig.jpg",
"is_private": 1,
"is_home_folder": 0,
"is_attachments_folder": 0,
"file_size": 96392,
"file_url": "/private/files/Trump-Sad-Pig.jpg",
"thumbnail_url": null,
"folder": "Home/Attachments",
"is_folder": 0,
"attached_to_doctype": "Sales Invoice",
"attached_to_name": "ACC-SINV-2020-00001",
"attached_to_field": null,
"old_parent": null,
"content_hash": "e5d16af3081403db0ad9e6eb0ec8dfdd",
"uploaded_to_dropbox": 0,
"uploaded_to_google_drive": 0,
"doctype": "File"
}
}
… and then my site files directories look like this …
private
├── backups
└── files
├── Trump-Sad-Pig.jpg
├── UOM.csv
└── docType_Chart_of_Accounts_Importer.csv
public
└── files
… my Sales Invoice
like this …
… and my Attachments
subsection like this …
Clicking on the indicated file link gets me to the file meta-data and thumbnail:
Notes:
-
"decode_base64=1"
- text (JSON, XML) arrives intact and properly formatted without needing this to be set.
-
-H "Authorization: token ${ERP_KEY}:${ERP_SCT}"
- the older, alternate RPC method upload_file
only works with basic authentication. For permanent server to server comms, frappe.client.attach_file
works much better.
-
"is_private=1"
- if this is left false
the file will be placed in public/files
-
"filename=${THEFILE}"
- The name here does not need to be the same as original file on the uploader machine. If you upload a file with the same name, but different content, the File Manager
accepts any number of repeated identical names. Files are distinguished by content hash not by name.