Upload avatar image with API

I’m trying to upload an avatar image with the API as follows. I’m getting back a 500 error and I don’t see anything in the Error Logs on the server, via the Admin user.

I’ve attached a picture with the data from a Postman POST.

Of note is that I had this working at one time but then something changed and it stopped working. I’m not sure what changed, besides an update to Discourse and Docker.

إعجاب واحد (1)

So in order to change the avatar via the api you will need to make 2 api requests.

POST {{base_url}}/uploads.json
form-data:
  api_key: {{api_key}}
  api_username: {{api_username}}
  type: avatar
  user_id: 1
  files[]: file

The problem I found is that this just returns { "success": "OK" } and doesn’t return the upload_id?

Then you need to make a request with the upload_id:

PUT {{base_url}}/users/{{api_username}}/preferences/avatar/pick
form-data:
  api_key: {{api_key}}
  api_username: {{api_username}}
  upload_id: 2
  type: uploaded
إعجابَين (2)

Yep, that’s what I found. I can’t figure out how to get the upload_id. Anybody know how to do that?

Like I said, this was working before the Discourse and Docker were updated.

إعجاب واحد (1)

How would I find the changelog around the upload API? This worked before I did an update of Discourse. The update was large, as it was about a year old.

Previously I did it this way:
POST to {base_url}/users/{username}/preferences/user_image?api_key={key}&api_username={username}
followed by
POST to {base_url}/users/{username}/preferences/avatar/pick?upload_id={id}api_key={key}&api_username={username}

The upload_id was returned by the first POST. This flow is not working anymore. Does anybody know what might have changed? Or how I can get it working again?

You need to connect to the message-bus and listen on /uploads - BEFORE sending the upload - just in case the resize operation takes a long time.

I think you also need to send your message bus client_id with the upload, too.

3 إعجابات

Is that available via API web calls?

There is supposed to be a synchronous option with uploads API as well and I can’t get that to work either. The synchronous option was supposed to return the upload_id. At least that is what I gathered from other posts here.

Okay I just verified that I got this to work. You just need to add the synchronous: true value to get the id.

now that we have the id: 17 we can then make one more request:

4 إعجابات

Thanks!! I will try it tonight, when I get home.

I noticed in your screenshot, that you have something in “Pre-request Script.” What is in there?

Your headers also should indicate multi-part, correct?

I don’t have anything in my headers.

My “Pre-request script” isn’t being used in these calls, but I use it to generate a random string with {{str}}:

postman.setEnvironmentVariable("str", Math.random().toString(36).slice(1, 16).replace(/\W/g, ''));

synchronous upload is only available for staff users. Non-staff users have to use the message bus method.

3 إعجابات

I’m guessing the message bus method is not available via the API calls?

It is, but it’s a very different API.
Here’s the client code:
https://github.com/SamSaffron/message_bus/blob/master/assets/message-bus.js

It’s possible to implement it in a PHP script for sure. I think I’ve either seen it done or done it myself before (don’t remember which).

Goes something like this:

  • start a new thread that posts to the message bus to register
  • back in main thread, once that kicks off, start the upload
  • 2nd thread loops until it gets the upload id, passes ID back to main thread, exits
  • main thread waits to get the ID from the bus thread (could be a thread.join())
6 إعجابات

I got that to work with a non-staff member. Not sure what I was doing wrong, but I had tried basically the same thing several times to no avail. One thing that I did different was I had some headers defined for “Accept” and “Content-Type”

Thanks for the help!!

إعجاب واحد (1)

I was wondering if it’s possible for an application to send a discord auth token to discourse to upload / download a file from discourse?

That is, currently users by default can upload up to 4096 KB for avatar pics. I have discord oauth already setup and working. Can an app communicate and send the same request (maybe via SSO?) to discourse to upload or download a file?

If so, how would that request from the app work?