uploading images with the nodebb-plugin-write-api

NodeBB Plugins
  • I'm having trouble uploading images using the nodebb-write-api plugin

    Here are the steps I've completed so far. The upload image nodebb-write-api example is at the bottom of this post.

    Create NodeBB Instance

    docker create --name myNodeBB --init --restart always -e url="http://192.168.0.41:4567" -p 4567:4567 -v nodebb-data:/var/lib/redis -v nodebb-files:/opt/nodebb/public/uploads -v nodebb-config:/etc/nodebb nilsramsperger/nodebb

    Start NodeBB Instance

    docker start myNodeBB

    Install https://github.com/NodeBB/nodebb-plugin-write-api/

    docker exec -it myNodeBB sh

    download NodeBB write-api plugin

    cd /opt/nodebb/node_modules

    wget https://github.com/NodeBB/nodebb-plugin-write-api/archive/refs/heads/master.zip

    unzip master.zip

    NodeBB activate the nodebb-plugin-write-api

    activate nodebb api write plugin

    Create a master token with uid 0

    master token uid 0

    Stop/Start NodeBB Instance

    docker stop myNodeBB

    docker start myNodeBB

    CREATE USER (WSL/Ubuntu)

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: application/json" \
    -d '{"username":"MY_USERNAME", "password":"MY_PASSWORD", "email":"[email protected]", "_uid":"1"}' \
    -X POST http://localhost:4567/api/v3/users/
    

    Make a User an Administarator

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: application/json" \
    -d '{"_uid":"1"}' \
    -X PUT http://localhost:4567/api/v3/groups/administrators/membership/2
    

    CREATE POST

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -d "title=api test post&content=the contents of the test post&cid=1&_uid=1" \
    -X POST http://localhost:4567/api/v3/topics
    

    Create post 2

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: application/json" \
    -d '{"title":"another user 2", "content":"content from a different user", "cid":"1", "_uid":"2"}' \
    -X POST http://localhost:4567/api/v3/topics
    

    Create Category

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: application/json" \
    -d '{"name":"category 1 name", "description":"category 1 description", "_uid":"2"}' \
    -X POST http://localhost:4567/api/v3/categories
    

    Create sub category (get parent category id)

    # list categories http://localhost:4567/api/categories
    "cid":"8" -> category 1 name
    

    Create Sub Category

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: application/json" \
    -d '{"parentCid":"8", "name":"sub category A", "description":"sub category A", "_uid":"1"}' \
    -X POST http://localhost:4567/api/v3/categories
    

    iamge uploads

    Image upload (doesn't work)

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: multipart/form-data" \
    -o '/mnt/c/Users/Terry/Downloads/myimg.jpg' \
    -o '/mnt/c/Users/Terry/Downloads/walrus.jpg' \
    -X POST http://localhost:4567/api/v3/util/_uid=1 
    
    
    [email protected]:/mnt/c/Users/Terry/Downloads$
    [email protected]:/mnt/c/Users/Terry/Downloads$ curl \
    thorizat> -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    > -H "Content-Type: multipart/form-data" \
    > -o '/mnt/c/Users/Terry/Downloads/myimg.jpg' \
    > -o '/mnt/c/Users/Terry/Downloads/walrus.jpg' \
    > -X POST http://localhost:4567/api/v3/util/_uid=1
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100    74  100    74    0     0  24666      0 --:--:-- --:--:-- --:--:-- 24666
    [email protected]:/mnt/c/Users/Terry/Downloads$ ll *.jpg
    -rwxrwxrwx 1 terry terry   74 Dec  4 16:17 myimg.jpg*
    -rwxrwxrwx 1 terry terry 4966 Dec  4 14:15 walrus.jpg*
    [email protected]:/mnt/c/Users/Terry/Downloads$
    

    Image isn't appearing in my uploads

    Thank you

  • I'm also trying to validate my curl upload to a diagnostic http inspector url

    http://httpbin.org/post

    My local NodeBB endpoint I'm substituting to the http://httpbin.org/post endpoint to validate my curl commands
    [http://localhost:4567/api/v3/util?_uid=1]

    (http://localhost:4567/api/v3/util?_uid=1)

    [email protected]:/mnt/c/Users/Terry/Downloads$ ls -l *.jpg
    -rwxrwxrwx 1 terry terry 13810 Dec  4 19:10 boat.jpg
    -rwxrwxrwx 1 terry terry  4966 Dec  4 14:15 walrus.jpg
    

    Some more examples I'm attempting

    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: image/jpeg, image/png" \
    -H "Content-Type: multipart/form-data" \
    -H "Accept: image/jpg, image/png" \
    -F '_uid=1' \
    -F 'files[]=@/mnt/c/Users/Terry/Downloads/walrus.jpg' \
    -F 'files[]=@/mnt/c/Users/Terry/Downloads/boat.jpg' \
    -X POST http://httpbin.org/post
    
    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -H "Content-Type: multipart/form-data" \
    -H "Content-Type: application/json" \
    -d '{"_uid":"1","uid":"1", "files":["boat.jpg", "walrus.jpg"]}' \
    -X POST http://httpbin.org/post
    
    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -F '_uid=1' \
    -F 'files[]=@/mnt/c/Users/Terry/Downloads/boat.jpg' \
    -X POST http://httpbin.org/post
    

    My Curl command's all return a not-found message

    {"status":{"code":"not-found","message":"Invalid API call"},"response":{}}
    

    Thank you

  • I found more upload utils...I should have checked here first. This is exactly what I need.

    image docs

  • The way I'm organizing my curl is "forbidden" to my instance to NodeBB. So, I must be making an incorrectly formed cURL.

    A test post to http://httpbin.org/post

    curl \
    -v -L \
    -F "folder=files" \
    -F files[][a]=@/mnt/c/Users/Terry/Downloads/walrus.txt \
    -F files[][b]=@/mnt/c/Users/Terry/Downloads/boat.txt \
    -X POST http://httpbin.org/post
    
    {
      "args": {}, 
      "data": "", 
      "files": {
        "files[][a]": "/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUA\nAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAARAAAATgAAAAAAAABgAAAGiaZpqgWtjDEe7BeT+\nNSM0QyrTvP29KYDGuHbpxTOT1oEJjFLTEFIRTAWigBM0UAOpaYC4oxSAMUYoAdS0AHFFIApaBjTS\nEUAN2ijaPSkAmKXFMBCKMUxBijFACEUAUAGKKAHUtMBfyozSAPzpaAFpKAFopALSUAJRQMMUYoAT\nFGKYhCKTFABijFIBKKYCYooAdTgKYAaKQCig8UALmigAooAUdKQ0gCimwAUlCAWkoAQ0UAFIaAEo\nNIBKKYH/2Q==[SNIPPED FOR BEVITY]\n", 
        "files[][b]": "/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAgEbAAUA\nAAABAAAARgEoAAMAAAABAAIAAAExAAIAcGFpbwYKCAICwoKCw4YEA4NBMOjqehU5BFAHQCnDiu45Rc0uSRigBVGBinA0AGaM0AKKeKYwJpCeKQBRQAooHWgBr/wCsUelOzTGLSZoAKXNJ\ngJ2pM0CEJPagE5oGOzSg00IM0jUhjScVYQ/KKTGQ3sRePevVevFUAQ3KPk1IxD6n7wpMknOaQB3N\nJkfjSYCEE9KuWN48LbWBZO+O1UnYTNbKuA64ORwaDzWiII2qC6gFzA0TdDUS2LicmylWKnqDg03N\nchshKKGMKKQBRQAUUwP/2Q==[SNIPPED FOR BEVITY]\n"
      }, 
      "form": {
        "folder": "files"
      }, 
      "headers": {
        "Accept": "*/*", 
        "Content-Length": "25811", 
        "Content-Type": "multipart/form-data; boundary=------------------------431f7f6f86548cef", 
        "Host": "httpbin.org", 
        "User-Agent": "curl/7.68.0", 
        "X-Amzn-Trace-Id": "Root=1-638e16a9-2f0bb89e1fb0a56001a2da1a"
      }, 
      "json": null, 
      "origin": "188.241.83.123", 
      "url": "http://httpbin.org/post"
    }
    

    A post to my NodeBB localhost

    curl \
    -v -L \
    -F "folder=files" \
    -F files[][a]=@/mnt/c/Users/Terry/Downloads/walrus.txt \
    -F files[][b]=@/mnt/c/Users/Terry/Downloads/boat.txt \
    -X POST http://192.168.0.41:4567/api/admin/upload/file
    
    Note: Unnecessary use of -X or --request, POST is already inferred.
    *   Trying 192.168.0.41:4567...
    * TCP_NODELAY set
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 192.168.0.41 (192.168.0.41) port 4567 (#0)
    > POST /api/admin/upload/file HTTP/1.1
    > Host: 192.168.0.41:4567
    > User-Agent: curl/7.68.0
    > Accept: */*
    > Content-Length: 25811
    > Content-Type: multipart/form-data; boundary=------------------------4e23fe79b3f14644
    > Expect: 100-continue
    > 
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 100 Continue
    } [25811 bytes data]
    * We are completely uploaded and fine
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 403 Forbidden
    < Cross-Origin-Opener-Policy: same-origin
    < Cross-Origin-Resource-Policy: same-origin
    < X-DNS-Prefetch-Control: off
    < Expect-CT: max-age=0
    < X-Frame-Options: SAMEORIGIN
    < Strict-Transport-Security: max-age=15552000; includeSubDomains
    < X-Download-Options: noopen
    < X-Content-Type-Options: nosniff
    < Origin-Agent-Cluster: ?1
    < X-Permitted-Cross-Domain-Policies: none
    < Referrer-Policy: strict-origin-when-cross-origin
    < X-XSS-Protection: 0
    < X-Powered-By: NodeBB
    < Content-Security-Policy: frame-ancestors 'self'
    < Content-Type: text/plain; charset=utf-8
    < Content-Length: 9
    < ETag: W/"9-PatfYBLj4Um1qTm5zrukoLhNyPU"
    < Set-Cookie: express.sid=s%3A1oiGlSlGA091BEqIa92_K3c5PQZYCMU2.nV3uZBlygamefQQFgJcCJ8xznV%2Bdo3X49dm%2BkSMM0lU; Path=/; Expires=Mon, 19 Dec 2022 16:15:30 GMT; HttpOnly; SameSite=Lax
    < Date: Mon, 05 Dec 2022 16:15:30 GMT
    < Connection: keep-alive
    < Keep-Alive: timeout=5
    < 
    { [9 bytes data]
    
    100 25820  100     9  100 25811   1800  5041k --:--:-- --:--:-- --:--:-- 5042k
    * Connection #0 to host 192.168.0.41 left intact
    Forbidden
    

    Thank you
    (Sorry for all the posts, I would have deleted the other ones...when I saw the api/upload in the ReDocs

  • I found this post very helpful it is exactly what I'm looking for Update category picture (via image upload) API not working

    I noticed that the IP address used to start my instance of NodeBB also effects the results of my cURL endpoints.

    http://127.0.0.1:4567/api/admin/manage/uploads

    {"status":{"code":"not-authorised","message":"A valid login session was not found. Please log in and try again."},"response":{}}
    

    http://localhost:4567/api/admin/manage/uploads

    "currentFolder":"","showPids":false,"files":[{"name":"category","path":"category","url":"/assets/uploads/category","fileCount":0,"size":4096,"sizeHumanReadable":"4.0KiB","isDirectory":true,"isFile":false,"mtime":1670090052269.7588},{"name":"emoji","path":"emoji","url":"/assets/uploads/emoji","fileCount":0,"size":4096,"sizeHumanReadable":"4.0KiB","isDirectory":true,"isFile":false,"mtime":1670090123333.093},{"name":"files","path":"files","url":"/assets/uploads/files","fileCount":2,"size":4096,"sizeHumanReadable":"4.0KiB","isDirectory":true,"isFile":false,"mtime":1670125300133.004},{"name":"profile","path":"profile","url":"/assets/uploads/profile","fileCount":0,"size":4096,"sizeHumanReadable":"4.0KiB","isDirectory":true,"isFile":false,"mtime":1670090052269.7588},{"name":"sounds","path":"sounds","url":"/assets/uploads/sounds","fileCount":0,"size":4096,"sizeHumanReadable":"4.0KiB","isDirectory":true,"isFile":false,"mtime":1670090052269.7588},{"name":"system","path":"system","url":"/assets/uploads/system","fileCount":1,"size":4096,"sizeHumanReadable":"4.0KiB","isDirectory":true,"isFile":false,"mtime":1670090095112.16}],"breadcrumbs":[{"text":"Uploads","url":"/admin/manage/uploads"}],"pagination":{"prev":{"page":1,"active":false},"next":{"page":1,"active":false},"first":{"page":1,"active":true},"last":{"page":1,"active":true},"rel":[],"pages":[],"currentPage":1,"pageCount":1},"loggedIn":true,"relative_path":"","template":{"name":"admin/manage/uploads","admin/manage/uploads":true},"url":"/admin/manage/uploads","bodyClass":"page-admin page-admin-manage page-admin-uploads page-status-200 theme-persona user-loggedin","_header":{"tags":{"meta":[{"name":"viewport","content":"width&#x3D;device-width, initial-scale&#x3D;1.0"},{"name":"content-type","content":"text/html; charset=UTF-8","noEscape":true},{"name":"apple-mobile-web-app-capable","content":"yes"},{"name":"mobile-web-app-capable","content":"yes"},{"property":"og:site_name","content":"NodeBB"},{"name":"msapplication-badge","content":"frequency=30; polling-uri=http://192.168.0.41:4567/sitemap.xml","noEscape":true},{"name":"theme-color","content":"#ffffff"},{"property":"og:image","content":"http://192.168.0.41:4567/assets/images/[email protected]","noEscape":true},{"property":"og:image:url","content":"http://192.168.0.41:4567/assets/images/[email protected]","noEscape":true},{"property":"og:image:width","content":"963"},{"property":"og:image:height","content":"225"},{"content":"NodeBB","property":"og:title"},{"content":"http://192.168.0.41:4567/api/admin/manage/uploads","property":"og:url"}],"link":[{"rel":"icon","type":"image/x-icon","href":"/assets/uploads/system/favicon.ico?v&#x3D;8lgptiu7o1i"},{"rel":"manifest","href":"/manifest.webmanifest","crossorigin":"use-credentials"},{"rel":"apple-touch-icon","href":"/assets/images/touch/512.png"},{"rel":"icon","sizes":"36x36","href":"/assets/images/touch/36.png"},{"rel":"icon","sizes":"48x48","href":"/assets/images/touch/48.png"},{"rel":"icon","sizes":"72x72","href":"/assets/images/touch/72.png"},{"rel":"icon","sizes":"96x96","href":"/assets/images/touch/96.png"},{"rel":"icon","sizes":"144x144","href":"/assets/images/touch/144.png"},{"rel":"icon","sizes":"192x192","href":"/assets/images/touch/192.png"},{"rel":"icon","sizes":"512x512","href":"/assets/images/touch/512.png"},{"rel":"prefetch","href":"/assets/src/modules/composer.js?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/src/modules/composer/uploads.js?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/src/modules/composer/drafts.js?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/src/modules/composer/tags.js?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/src/modules/composer/categoryList.js?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/src/modules/composer/resize.js?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/src/modules/composer/autocomplete.js?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/templates/composer.tpl?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/language/en-GB/topic.json?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/language/en-GB/modules.json?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch","href":"/assets/language/en-GB/tags.json?v&#x3D;8lgptiu7o1i"},{"rel":"prefetch stylesheet","type":"","href":"/assets/plugins/nodebb-plugin-markdown/styles/default.css"},{"rel":"prefetch","href":"/assets/language/en-GB/markdown.json?v&#x3D;8lgptiu7o1i"},{"rel":"stylesheet","href":"http://192.168.0.41:4567/assets/plugins/nodebb-plugin-emoji/emoji/styles.css?v&#x3D;8lgptiu7o1i"}]}},"widgets":{"footer":[{"html":"<footer id=\"footer\" class=\"container footer\">\r\n\t<div>\r\n\t\tPowered by <a target=\"_blank\" href=\"https://nodebb.org\">NodeBB</a> | <a target=\"_blank\" href=\"//github.com/NodeBB/NodeBB/graphs/contributors\">Contributors</a>\r\n\t</div>\r\n</footer>"}]}}
    

    http://192.168.0.41:4567/api/admin/manage/uploads

    {}
    

    I'm looking at another post that allows the cURL https://curlconverter.com/ to be copied from the Chrome Developer Tools

    curl http://localhost:4567/api/config -c cookies.txt -s | grep -oP "(csrf_token.+?,)"
    

    csrf_token":"rvdKyoNf-N4cJqlHQq5mljvF6G_RHZsj-yKw",

    http://localhost:4567/api/v3/categories/1

    {"status":{"code":"ok","message":"OK"},"response":{"cid":1,"name":"Announcements","description":"Announcements regarding our community","descriptionParsed":"<p>Announcements regarding our community</p>\n","icon":"fa-bullhorn","bgColor":"#fda34b","color":"#ffffff","slug":"1/announcements","parentCid":0,"topic_count":13,"post_count":13,"disabled":0,"order":1,"link":"","numRecentReplies":1,"class":"col-md-3 col-xs-6","imageClass":"cover","isSection":0,"subCategoriesPerPage":10,"minTags":0,"maxTags":5,"postQueue":0,"totalPostCount":13,"totalTopicCount":13}}
    
    curl \
    -H "Authorization: Bearer 9413a049-8faa-49c0-8694-1eda2d93c4b0" \
    -F params='{"cid":"1", "uid":"1", "_uid":"1"}' \
    -F "files[]=@/mnt/c/Users/Terry/Downloads/walrus.jpg" \
    -F "_csrf=rvdKyoNf-N4cJqlHQq5mljvF6G_RHZsj-yKw"  \
    -F "csrf_token=rvdKyoNf-N4cJqlHQq5mljvF6G_RHZsj-yKw"  \
    -b cookies.txt \
    -X POST http://localhost:4567/api/admin/category
    

    Is currently giving me an error from the solution at Update category picture (via image upload) API not working

    {"path":"&#x2F;api&#x2F;admin&#x2F;category","error":"[[error:api.master-token-no-uid]]","bodyClass":"page-admin page-admin-category page-status-500 theme-persona user-guest"}
    

    Thank you

  • I was able to upload an empty image using the cURL from "Copy as cURL (bash)" in the Chrome developer tools to my WSL2/Ubuntu console.

    The "Copy as cURL (bash)" in the Chrome Developer tools doesn't explicitly set the folder name parameters or set the file[] binary data array for easy substitution.

    So, when I ran the "Copy as cURL (bash) from the Chrome Developer tools it uploaded an "empty" image of 0kb correctly named.

    curl 'http://localhost:4567/api/admin/upload/file' \
      -H 'Accept: */*' \
      -H 'Accept-Language: en-US,en' \
      -H 'Connection: keep-alive' \
      -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1bBgU3aYIkSJ4VmP' \
      -H 'Cookie: express.sid=s%3AnDMA0vghZZV7ASeMeHO4aWNQSxnBB9DI.fSrL2W%2FKwqGPNJ89wSIy9vfyee%2Bf%2F6Owgn9DGfiAwgc' \
      -H 'Origin: http://localhost:4567' \
      -H 'Referer: http://localhost:4567/admin/manage/uploads?dir=test' \
      -H 'Sec-Fetch-Dest: empty' \
      -H 'Sec-Fetch-Mode: cors' \
      -H 'Sec-Fetch-Site: same-origin' \
      -H 'Sec-GPC: 1' \
      -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' \
      -H 'X-Requested-With: XMLHttpRequest' \
      -H 'sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Brave";v="108"' \
      -H 'sec-ch-ua-mobile: ?0' \
      -H 'sec-ch-ua-platform: "Windows"' \
      -H 'x-csrf-token: lsg72Une-j32Vn4vtME7H_B3JB-jslxj4Mqw' \
      --data-raw $'------WebKitFormBoundary1bBgU3aYIkSJ4VmP\r\nContent-Disposition: form-data; name="files[]"; filename="walrus.jpg"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary1bBgU3aYIkSJ4VmP\r\nContent-Disposition: form-data; name="params"\r\n\r\n{"folder":"/test"}\r\n------WebKitFormBoundary1bBgU3aYIkSJ4VmP--\r\n' \
      --compressed
    

    How to get the "Copy as cURL (bash)
    upload.png

    Output from the cURL command from the Chrome Developer Tools

    [{"url":"/assets/uploads//test/walrus.jpg"}]
    

    So, I need to replace what is in the --data-raw

    --data-raw $'------WebKitFormBoundary1bBgU3aYIkSJ4VmP\r\nContent-Disposition: form-data; name="files[]"; filename="walrus.jpg"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary1bBgU3aYIkSJ4VmP\r\nContent-Disposition: form-data; name="params"\r\n\r\n{"folder":"/test"}\r\n------WebKitFormBoundary1bBgU3aYIkSJ4VmP--\r\n' \
    

    With something like:

    -F 'name=params: {"folder":"/test"}' \
    -F "files[1]=@/mnt/c/Users/Terry/Downloads/small.jpg" \
    

    Thank you

  • Got it!

    Tested the original cURL from the Browser Developer Tools against curl 'http://httpbin.org/post' (a post testing service)

    replaced:

    curl 'http://localhost:4567/api/admin/upload/file' \
    

    with:

    curl 'http://httpbin.org/post' \
    
    curl 'http://localhost:4567/api/admin/upload/file' \
      -H 'Accept: */*' \
      -H 'Accept-Language: en-US,en' \
      -H 'Connection: keep-alive' \
      -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycWHrDFflR4bC1tZQ' \
      -H 'Cookie: express.sid=s%3A3aOlEybRIA-2ETDSLhzJbAAeFBbDqRSY.aqBLldxcKQCncS7C4NDqd7tD9lsXLWdbw2wA4P8HwoE' \
      -H 'Origin: http://localhost:4567' \
      -H 'Referer: http://localhost:4567/admin/manage/uploads?dir=test' \
      -H 'Sec-Fetch-Dest: empty' \
      -H 'Sec-Fetch-Mode: cors' \
      -H 'Sec-Fetch-Site: same-origin' \
      -H 'Sec-GPC: 1' \
      -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' \
      -H 'X-Requested-With: XMLHttpRequest' \
      -H 'sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Brave";v="108"' \
      -H 'sec-ch-ua-mobile: ?0' \
      -H 'sec-ch-ua-platform: "Windows"' \
      -H 'x-csrf-token: aUs0HZSZ-EBNli65aMwZw-vKpHAdZAz02X7k' \
      --data-raw $'------WebKitFormBoundarycWHrDFflR4bC1tZQ\r\nContent-Disposition: form-data; name="files[]"; filename="small.jpg"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundarycWHrDFflR4bC1tZQ\r\nContent-Disposition: form-data; name="params"\r\n\r\n{"folder":"/test"}\r\n------WebKitFormBoundarycWHrDFflR4bC1tZQ--\r\n' \
      --compressed
    

    output from original cURL a 'http://httpbin.org/post'
    endpoint

    {
      "args": {}, 
      "data": "", 
      "files": {
        "files[]": ""
      }, 
      "form": {
        "params": "{\"folder\":\"/test\"}"
      }, 
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "deflate, gzip, br", 
        "Accept-Language": "en-US,en", 
        "Content-Length": "297", 
        "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundarycWHrDFflR4bC1tZQ", 
        "Cookie": "express.sid=s%3A3aOlEybRIA-2ETDSLhzJbAAeFBbDqRSY.aqBLldxcKQCncS7C4NDqd7tD9lsXLWdbw2wA4P8HwoE", 
        "Host": "httpbin.org", 
        "Origin": "http://localhost:4567", 
        "Referer": "http://localhost:4567/admin/manage/uploads?dir=test", 
        "Sec-Ch-Ua": "\"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"108\", \"Brave\";v=\"108\"", 
        "Sec-Ch-Ua-Mobile": "?0", 
        "Sec-Ch-Ua-Platform": "\"Windows\"", 
        "Sec-Fetch-Dest": "empty", 
        "Sec-Fetch-Mode": "cors", 
        "Sec-Fetch-Site": "same-origin", 
        "Sec-Gpc": "1", 
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", 
        "X-Amzn-Trace-Id": "Root=1-638ebf1a-210ae56e75b7fa2022a9c650", 
        "X-Csrf-Token": "aUs0HZSZ-EBNli65aMwZw-vKpHAdZAz02X7k", 
        "X-Requested-With": "XMLHttpRequest"
      }, 
      "json": null, 
      "origin": "212.102.44.170", 
      "url": "http://httpbin.org/post"
    }
    

    works!

    removed:

    "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundarycWHrDFflR4bC1tZQ",
    

    and replaced the --data-raw from the original with

    --form "params={\"folder\":\"/test\"}" \
    --form "files[]=@/mnt/c/Users/Terry/Downloads/small.jpg"
    
    curl 'http://localhost:4567/api/admin/upload/file' \
      -H 'Accept: */*' \
      -H 'Accept-Language: en-US,en' \
      -H 'Connection: keep-alive' \
      -H 'Cookie: express.sid=s%3A3aOlEybRIA-2ETDSLhzJbAAeFBbDqRSY.aqBLldxcKQCncS7C4NDqd7tD9lsXLWdbw2wA4P8HwoE' \
      -H 'Origin: http://localhost:4567' \
      -H 'Referer: http://localhost:4567/admin/manage/uploads?dir=test' \
      -H 'Sec-Fetch-Dest: empty' \
      -H 'Sec-Fetch-Mode: cors' \
      -H 'Sec-Fetch-Site: same-origin' \
      -H 'Sec-GPC: 1' \
      -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' \
      -H 'X-Requested-With: XMLHttpRequest' \
      -H 'sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Brave";v="108"' \
      -H 'sec-ch-ua-mobile: ?0' \
      -H 'sec-ch-ua-platform: "Windows"' \
      -H 'x-csrf-token: aUs0HZSZ-EBNli65aMwZw-vKpHAdZAz02X7k' \
    --form "params={\"folder\":\"/test\"}" \
    --form "files[]=@/mnt/c/Users/Terry/Downloads/small.jpg" \
      --compressed
    

    This works!

    I'm going to try to find more efficiencies in the above cURL upload command

    Thank you

  • "A" minimal cURL command to upload an image

    curl 'http://localhost:4567/api/admin/upload/file' \
    -H 'Cookie: express.sid=s%3A3aOlEybRIA-2ETDSLhzJbAAeFBbDqRSY.aqBLldxcKQCncS7C4NDqd7tD9lsXLWdbw2wA4P8HwoE' \
    -H 'x-csrf-token: aUs0HZSZ-EBNli65aMwZw-vKpHAdZAz02X7k' \
    --form "params={\"folder\":\"/test\"}" \
    --form "files[]=@/mnt/c/Users/Terry/Downloads/small.jpg"
    

    Thank you

  • @lostspace just so you know you're not blasting posts into a black hole that nobody ever sees....

    Thanks for the information you've provided. The API can be difficult to understand and work with, and the examples you've posted will undoubtedly help others in the same journey.


Suggested Topics