@fisher1
Strangely enough, I uploaded my first file to Canvas using the API just a few weeks ago. I was getting tired of manually uploading my trig lecture notes after I changed them and recompiled the LaTeX, so I wrote a script that would scan the folders on a local disk and compare them to the files inside Canvas, updating the files in Canvas when they local file was newer.
It took some trial and error to get it working properly. The thing that I thought would give me trouble, but ended up not, was the step 3: confirm the upload's success. I told my request to follow redirects and that worked.
I was only uploading a few files at a time (40 at most), definitely not what you would call a bulk avatar upload.
I notice in the source code that they have allow_redirects=False. I don't do any Canvas work in Python (I don't do much in Python), but based on what I found that with Node JS, that could be set to true and then skip step 3.
Here's my step 2. I took the upload_url returned from step 1. I then created a form and copied all of the upload_params over. Then I added a file parameter to my form as the last thing. However, it was still part of the form.
Here are some questions I would probably know the answer to if I used Python.
- Python is synchronous and requests are made in serial format? I've been using promises in JavaScript and have to use a lot of then statements to wait for the promise to finish before moving on.
- Is it the same file that fails every time or is it just after a bunch of them? That's tied to the synchronous nature. If too many calls are made asynchronously, like with JS promises, then you could hit the rate limiting. But if you can only make one call at a time, that shouldn't be an issue.
- The upload_file_res request has files=files in it. Does it manually add a form entry for file? I had to add the file parameter to the form itself. That's probably irrelevant since you said that's not the part having issues, but you also mentioned not using the upload URL that the request returned.
- Is there something different about the student that fails? An extra space in there somewhere? I normally add trim() to my code even though I'm the person creating the file, just to make sure. Maybe that student has a profile picture already?
- Is there something different about the file that fails than the others? For example, does it have capital letters or special characters in it?
You might try some debugging. For example, print out the inform_parameters object before you make the request and see if it's got something unusual in it before the request that gets hung up. I would also print the result and look for something unusual there.
You say it's hanging up on the "Done prepping for Canvas", but you don't really know that because there is no print statement in step 2. It might be step 3 or 4 that is failing. Make sure that the data object (end of step 1) has upload_params and upload_url in it. Then print the results of upload_file_res at the end of step 2 to make sure it's giving you what you think it should.
In step 3, the script is unilaterally making a get post call. First, it may not be necessary, you should check the http status from step 2. More importantly, the documentation says to make a get, not a post. That said, the example request shows a post with a content-length of 0. You're not specifying a content-length of 0, but that might be something that Python does for you. Still, the documentation reads like it should be a get. That's why my following redirects worked.
In step 4, why are you masquerading as the user when fetching the avatar information when you're specifying the user ID? I would also add a check to make sure that the type is attachment as all three types have a display name. You might also consider printing the display_name for each record to make sure it's not failing to find one. That may not be necessary, but it might be trying to get a token that doesn't exist. This is unlikely to be the problem -- you just asked me to troubleshoot a programming language I rarely use and a script I have never used and it's almost 2 am and I should have been in bed a couple of hours ago since I have to teach this morning so my mind is asking things it might not if I had more time.
In general, the script doesn't do any error checking. It could be a failed network request that is causing the problem. It just plows ahead like everything works without checking that it does. That could lead to a hang, which is why I'm suggesting adding debugging by printing what is sent and what is returned by the requests. I also have ran into trouble in my own scripts where I think something is right but I end up having a null inside a request (ex: /api/v1/courses/null/users) -- and of course, it fails.