1

Here's my understanding of the desired sequence of operations when uploading a file to an entity's dropbox submission:

  1. Create feedback for a user (in my case, I am populating a rubric assessment automatically)
  2. Upload a file, receive unique file key
  3. Attach that file to the user's feedback, using the key received in (2)

I can upload a file for the user using the web interface to d2L, but obviously would like to streamline this if I am preparing the feedback through automation anyway. My current status is:

  1. Create feedback for a user (in my case, I am populating a rubric assessment automatically) (200 - Success)
  2. Upload a file, receive unique file key (200 - Success)
  3. Attach that file to the user's feedback, using the key received in (2) (404 - Not Found)

I've been struggling with how to debug uploading and attaching a file to a dropbox feedback. I followed the resumable upload instructions at http://docs.valence.desire2learn.com/basic/fileupload.html#resumable-uploads, and (generally) that went OK, but I'm getting a final 404 error when attaching that uploaded file to the dropbox folder for this entity.

Below is my debug output that demonstrates what I understand as the state of the system for me.

Note: I replaced COURSEID, DROPBOXID, ENTITYID, and a few Keys using search and replace in an external editor, to preserve the illusion of security.

POST /d2l/api/le/1.4/COURSEID/dropbox/folders/DROPBOXID/feedback/user/ENTITYID

Posts the feedback to the dropbox for this user

{}

Confirms that the post was successful

filepath=092215-0952/Testing Download Sep 21, 2015 1114 AM_upload/ENTITYID-DROPBOXID - Student Name-Due 18, YYYY TIME AM - netid_assignmentname.zip_upload.zip
length=76630
https://d2l.domain.tld/d2l/api/le/1.4/COURSEID/dropbox/folders/DROPBOXID/feedback/user/ENTITYID/upload?x_b=_________USERID___________&x_c=_________KEY_I_DONT_UNDERSTAND___________&x_a=_________APP_ID___________&x_d=_________ANOTHER_KEY_I_DONT_UNDERSTAND___________&x_t=1443053113
{'Content-Length': '76630', 'User-Agent': 'python-requests/2.7.0 CPython/3.3.6 Darwin/14.5.0', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'Accept': '*/*', 'X-Upload-Content-Type': 'application/zip', 'X-Upload-File-Name': 'temp.zip', 'X-Upload-Content-Length': '76630'}
Received new URL to which to upload this file: revising post for this fileKey
result=qafSoMUYAm
https://d2l.domain.tld/d2l/upload/qafSoMUYAm
result of revised post is 200

With this, it seems that I initiated, and completed, the resumable upload. I will say, this part was made easier by the instructions from valence, but there was a lot of muttering on my part trying to debug it until I realized that some of the built-in post commands in d2lservice would always fail since I had to change the URL after the first post. :) By the way, I can make this return a 416 if I intentionally mess up the byte count for the file length. I did this to make sure that I wasn't getting 200 for the wrong reason.

fileKey=qafSoMUYAm, attaching to the dropbox now
GET /d2l/api/le/1.1/COURSEID/dropbox/folders/DROPBOXID/feedback/user/ENTITYID
Feedback exists for org_unit_id=COURSEID,folder_id=DROPBOXID,entity_id=ENTITYID

Here, I am making sure that the feedback truly exists for this user, so I can compare the URL to the one that fails below. NOTE: I am using version 1.4 for almost everything, but in the example below I was hardcoding the version to be 1.1 in case there was a version difference in the APIs; I tried 1.1, 1.4, but nothing else.

I am also force-marking the feedback to be feedback['IsGraded']=False, in case for some reason it's not possible to add a file to feedback if the feedback has been published. I then re-post the feedback (after marking it as ungraded), and attempt to attach the uploaded file to this feedback. An additional variable is that I have also tried (and removed) the use of a fileName param for the post (it is listed as optional in the APIs).

POST /d2l/api/le/1.4/COURSEID/dropbox/folders/DROPBOXID/feedback/user/ENTITYID
I am turning on debug now...
ready for POST=/d2l/api/le/1.1/COURSEID/dropbox/folders/DROPBOXID/feedback/user/ENTITYID/attach
INFO:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): d2l.domain.tld
send: b'POST /d2l/api/le/1.1/COURSEID/dropbox/folders/DROPBOXID/feedback/user/ENTITYID/attach?fileKey=qafSoMUYAm&x_b=_________USERID___________&x_a=_________APP_ID___________&x_d=sw6PXGCvBOsBj07VJCPu4RJ6hN8AN7OIId2ONOj-_CA&x_t=1443053116&x_c=LIrzfSOnb8rz3wkN-ZTbfnckwvrfheUU9kkarOhGpok HTTP/1.1\r\nHost: d2l.domain.tld\r\nConnection: keep-alive\r\nUser-Agent: python-requests/2.7.0 CPython/3.3.6 Darwin/14.5.0\r\nContent-Length: 0\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate\r\n\r\n'
reply: 'HTTP/1.1 404 Not Found\r\n'
DEBUG:requests.packages.urllib3.connectionpool:"POST /d2l/api/le/1.1/COURSEID/dropbox/folders/DROPBOXID/feedback/user/ENTITYID/attach?fileKey=qafSoMUYAm&x_b=_________USERID___________&x_a=_________APP_ID___________&x_d=sw6PXGCvBOsBj07VJCPu4RJ6hN8AN7OIId2ONOj-_CA&x_t=1443053116&x_c=LIrzfSOnb8rz3wkN-ZTbfnckwvrfheUU9kkarOhGpok HTTP/1.1" 404 0

So, I get a 404 when trying to make this post, and a bunch of errors below from Python that don't really help (but I include them anyway).

header: Server header: X-XSS-Protection header: X-UA-Compatible header: X-Powered-By header: Date header: Content-Length header: Set-Cookie <Response [404]>
Traceback (most recent call last):
  File "../valence/sprinkle/production/postgradenoui.py", line 239, in <module>
    print(postGrades_handler(dropboxid, gradeddirname,gradeddir_uploadname))
  File "../valence/sprinkle/production/postgradenoui.py", line 230, in postGrades_handler
    result = sprinkleutil.postRubricFeedback(request, _ac, dropboxid, gradeddirname, _CFG_COURSE['courseorgunit'], gradeddir_uploadname)
  File "/Users/sprinkle/work/teaching/ece275-2015F/grading/valence/sprinkle/production/sprinkleutil.py", line 1279, in postRubricFeedback
    upload_feedback_files_for_dropbox_feedback(uc,orgunitNeeded,dropboxNeeded,dir,dbfFile,'1.4')
  File "/Users/sprinkle/work/teaching/ece275-2015F/grading/valence/sprinkle/production/sprinkleutil.py", line 791, in upload_feedback_files_for_dropbox_feedback
    result = attach_uploaded_file(uc,org_unit_id,folder_id,entity_id,fileKey,'temp.zip')
  File "/Users/sprinkle/work/teaching/ece275-2015F/grading/valence/sprinkle/production/sprinkleutil.py", line 523, in attach_uploaded_file
    return d2lservice._fetch_content(r)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/d2lvalence_util/service.py", line 46, in _fetch_content
    r.raise_for_status()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/requests/models.py", line 851, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found

I appreciate any pointers from anyway who has successfully carried out this sequence of operations. My d2l admins don't have bandwidth to support me, and I'm not sure if I can access the logs at all, so I don't know how to improve debugging on my side. Thanks in advance!

1 Answers1

0

For your attach stage, it looks like you're sending in the fileKey as a query parameter. It needs to be a POST form parameter, right?

So the content-type for the POST would be application/x-www-form-urlencoded, and the POST body itself would be

fileKey=qafSoMUYAm&fileName=SomeFileName.zip

For example, see How to mimic an HTML form submission in a POST request.

Community
  • 1
  • 1
Viktor Haag
  • 3,363
  • 1
  • 18
  • 21
  • I was working on similar task and I am sure this must work – Vitalii Boiarskyi Oct 29 '15 at 12:27
  • I am regrettably still receiving no love, but I will keep trying. I was hoping to use the API Test Tool from valence, but there is no application/x-www-forum/urlencoded to test it. Should it be possible to send these data via JSON instead? I tried but no luck... – Jonathan Sprinkle Nov 12 '15 at 01:10
  • @victor-haag I'm still struggling with this, could you confirm the below is "right"? send: b'POST /d2l/api/le/1.4/COURSEID/dropbox/folders/DROPBOXID/feedback/user/USERID/attach?x_b=_________USERID___________&x_a=_________APP_ID___________&x_d=____something_else____&x_t=1443053116&x_c=____something_else_again_____ HTTP/1.1\r\nHost: d2l.domain.tld\r\nAccept: */*\r\nContent-Type: application/x-www-forum-urlencoded\r\nContent-Length: 18\r\nConnection: keep-alive\r\nUser-Agent: python-requests/2.7.0 CPython/3.3.6 Darwin/14.5.0\r\nAccept-Encoding: gzip, deflate\r\n\r\nfileKey=2lIVkRyXEc' – Jonathan Sprinkle Nov 14 '15 at 18:33
  • I believe you can't just provide the file key here; don't you also have to provide the file name, as in the example in my answer? – Viktor Haag Jan 04 '16 at 20:14
  • The APIs list it as optional, I have tried it both ways and to no avail. I have also used urlencode to remove spaces and other chars from the .zip filename (though I don't know if this was needed). – Jonathan Sprinkle Jan 07 '16 at 22:59
  • It looks like the solution is to use application/x-www-form-urlencoded (the above recommendation for use of application/x-www-forum-urlencoded is a typo, so that POST type doesn't exist, and generates the 404). :) – Jonathan Sprinkle Jan 08 '16 at 04:08
  • Ah. My fault for the typo. Apologies. 8( – Viktor Haag Jan 11 '16 at 20:18