Question

I am having trouble uploading a profile picture for a user. I keep getting a 404 error, which the API docs tells me indicates the profile can't be found. However, above the code I'll display in a sec, I have code to retrieve the profile, and it does exist for the particular userId I'm using. Additionally:

  • This is with the PHP SDK
  • The account I used to authenticate with does have access to edit user profiles
  • The test image I'm using does exist and I am able to read it

Here's my code. It's a little sloppy, but I'll clean it up once I get this going for this particular test user:

$file = "testimage.jpeg";
$image_data = file_get_contents($file);

// Build our data
$uid = uniqid();
$data = "--" . $uid . "\r\n".
    "Content-Disposition: form-data; name=\"profileImage\"; filename=\"profileImage.jpeg\"\r\n".
    "Content-Type: image/jpeg\r\n".
    "\r\n".
    $image_data . "\r\n".
    "--" . $uid . "--";

$success = false;
$tryAgain = true;
$numAttempts = 1;
$url = "/d2l/api/lp/1.0/profile/user/".$userId."/image";
$uri = $opContext->createAuthenticatedUri($url, "POST");
curl_setopt($ch, CURLOPT_URL, $uri);
while ($tryAgain && $numAttempts < MAX_NUM_ATTEMPTS) {
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Disposition: multipart/form-data; boundary='.$uid,
        'Content-Length: ' . strlen($data))
    );
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

    $response = curl_exec($ch);
    $httpCode  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    $responseCode = $opContext->handleResult($response, $httpCode, $contentType);
    if ($responseCode == D2LUserContext::RESULT_OKAY) {
        $success = true;
        $tryAgain = false;
    }
    elseif ($responseCode == D2LUserContext::RESULT_INVALID_TIMESTAMP) {
        // Try again since time skew should now be fixed.
        $tryAgain = true;
    }
    else {      // Something bad happened
        echo "here:\r\n".
            $httpCode.
            "\r\n\r\n".
            $responseCode;
        exit;
    }
    $numAttempts++;
}

I'm at a loss as to what I'm missing. Any advice would be greatly appreciated. Thanks

Edit: I just noticed this section in the API docs:

Note

In order to use this action, the service must have granted the application specific permission to do so (that is, granted permission to the specific application ID and key to attempt this action).

I'll inquire if our app ID/Key does indeed have permission. I thought it did, but maybe I was given incorrect information. I'll inquire about this.

Was it helpful?

Solution

Here is a function that I use that works. I use the PHP Api to get an user context object and do the rest through curl.

$opContext - from the PHP API

$user_id - from d2l

$filename - image filename on server

$filepath - path to file on server (I have faculty and students in different places)

$filetype - for the mimetype

static function set_user_image($opContext,$user_id,$filename,$filepath,$filetype){
    $fp = fopen($filepath.$filename, 'r');
    $contents = fread($fp, filesize($filepath.$filename));
    fclose($fp);
    $random_hash = "xxBOUNDARYxx";
    $request ="--".$random_hash."\r\nContent-Type: application/json\r\n\r\n{\"Text\":\"Some comment\", \"HTML\":null}\r\n\r\n--".
                   $random_hash."\r\nContent-Disposition: form-data; name=\"profileimage\"; filename="."\"$filename\""."\r\nContent-Type: image/$filetype\r\n\r\n".
                   $contents."\r\n\r\n--".$random_hash;

    $length=strlen($request);
    $url = $opContext->createAuthenticatedUri("/d2l/api/lp/1.1/profile/user/$user_id/image","POST");

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$url); 
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("HTTP/1.1", "Content-Type: multipart/form-data; boundary=xxBOUNDARYxx","Content-Length:".$length));
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST,true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
    $response = curl_exec($ch);             
}   
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top