[solved] cURL example of an attachment upload RPC call?

I need to use the RPC API to attach a few files to a specified Sales Invoice.

I would be most grateful if somone could point me to a worked through and working example of how that is done?

I’m using:

ERPNext:  v12.7.1 (version-12)
Frappe Framework:  v12.5.1 (version-12)
Description: Ubuntu 18.04.4 LTS
Codename: bionic

there is:

frappe.utils.file_manager.add_attachments(doctype, name, attachments)

does it work for you?

2 Likes

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.

9 Likes

*** UPDATES 2020/06/15 ***

If you wish for the file to be public this will not work:

      :           :           :           
--data-urlencode "docname=${DOCID}" \
--data-urlencode "is_private=0" \
--data-urlencode "decode_base64=1" \

However, this will:

       :           :           :           
--data-urlencode "docname=${DOCID}" \
--data-urlencode "decode_base64=1" \

Also note that if you attempt to upload a file that’s already present, even if you try to give it a different name, you’ll get an error (409 I believe, “content conflict”) because the content exists already.

2 Likes

In addition to Martin’s excellent coverage of using cURL to upload a file, I’ve written a general tutorial on using cURL for both RPC and REST API calls. Hope it helps someone …

1 Like

where I need to write the scripts???

Any computer anywhere that has curl installed.

These are Linux command line scripts.

You need to find a tutorial somewhere about using the curl command.

You should probably also read about REST APIs ( Representational state transfers and application programmer interfaces)

The basic idea is that while HTTP/HTML made it very easy for human beings to get data out of computers somewhere else on the planet, it made getting data from HTML stupid hard for computers to do. REST APIs are like web pages for computers to read.