Search code examples
phpapirestdropboxdesire2learn

Submitting a file to the Desire2Learn Dropbox via PHP


I'm trying to use PHP to submit a file to the Desire2Learn Dropbox. I've gathered the file on the proxy no problem; it's trying to transfer the file from the proxy to the Dropbox where a problem occurs. I'm using their Valence API.

The user context for making this call has adequate permissions on the system to do so.

The error is "Unknown error occured".

$attachment=$_FILES["file"]["tmp_name"];
$attachmentName=$_FILES["file"]["name"];
$type=$_FILES["file"]["type"];
$file_name_with_full_path="files_dir/" . $_FILES["file"]["name"];
$file_to_upload = array('file_contents'=>'@'.$file_name_with_full_path); 

require_once 'libsrc/D2LAppContextFactory.php';
$errorArray = array(
    D2LUserContext::RESULT_OKAY => "Success",
    D2LUserContext::RESULT_INVALID_SIG => "Invalid signature.",
    D2LUserContext::RESULT_INVALID_TIMESTAMP => "There is a time skew between server and local machine.  Try again.",
    D2LUserContext::RESULT_NO_PERMISSION => "Not authorized to perform this operation.",
    D2LUserContext::RESULT_UNKNOWN => "Unknown error occured"
);

$port=443;
$host="subdomain.domain.com";

session_start();
foreach (array('appId', 'appKey', 'userId', 'userKey') as $e) {
    if (!isset($_SESSION[$e]) || $_SESSION[$e] == '') {
        die("Missing $e.  Please authenticate first.");
    }
}

$appKey = $_SESSION['appKey'];
$appId = $_SESSION['appId'];
$userId = $_SESSION['userId'];
$userKey = $_SESSION['userKey'];
session_write_close();

$authContextFactory = new D2LAppContextFactory();
$authContext = $authContextFactory->createSecurityContext($appId, $appKey);
$opContext = $authContext->createUserContext($host, $port, true, $userId, $userKey);

$target_url = $opContext->createAuthenticatedUri('/d2l/api/le/1.0/00004/dropbox/folders/00007/submissions/mysubmissions/', 'POST');

$ch = curl_init(); 

$random_hash = md5(date('r', time()));
$comment = array('Text'=>'some comment','HTML'=>null);
$comment = json_encode($comment);

$fp = fopen("files_dir/" . $_FILES["file"]["name"], 'rb');

ob_start(); //Turn on output buffering 
fpassthru($fp);
$filedata = ob_get_clean();

$request_pre="--".$random_hash."\r\nContent-Type: application/json\r\n".$comment."\r\n--".$random_hash."\r\nContent-Disposition:form-data; name=\"\"; filename=".$attachmentName."\r\nContent-Type:".$type."\r\n\r\n".$filedata."\r\n--".$random_hash."--\r\n";

$request=nl2br($request_pre);

$length=strlen($request);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("HTTP/1.1", "Content-Type: multipart/mixed; boundary=".$random_hash,"Host:".$host, "Content-length: ".$length));
curl_setopt($ch, CURLOPT_URL,$target_url); 
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request); 
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_CAINFO, getcwd().'/cacert.pem');
$response = curl_exec($ch);
$httpCode  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
$responseCode = $opContext->handleResult($response, $httpCode, $contentType);
$error_no = curl_errno($ch);

fclose($fp);

if ($responseCode == D2LUserContext::RESULT_OKAY) {
    $ret = "$response";
    $tryAgain = false;
} elseif ($responseCode == D2LUserContext::RESULT_INVALID_TIMESTAMP) {
    $tryAgain = true;
} else {
    $ret = "{$errorArray[$responseCode]}<br/>$response";
    $tryAgain = false;
}
if ($error_no == 0) {
    $error = 'File uploaded succesfully.';
} else {
    $error = 'File upload error.';
}
echo "error: ".$error."<br/>";


curl_close ($ch); 
echo $result; 

The POST fields look like this (the file doesn't look right to me '86761').

--565cef73df4da0f072b9626f4fae7e50
Content-Type: application/json
{"Text":"some comment","HTML":null}
--565cef73df4da0f072b9626f4fae7e50
Content-Disposition:form-data; name=""; filename="example.pdf"
Content-Type:application/pdf
{86761}
--565cef73df4da0f072b9626f4fae7e50--

Unknown error occured
error: File uploaded successfully

Solution

  • I would try adding a simple text file of type text/plain first to see if that works. Using your code (with some modifications) I was able to submit a file to a dropbox in Valence.

    // read file
    $fp = fopen($location, 'r');
    $contents = fread($fp, filesize($location));
    fclose($fp);
    
    $request_pre="--".$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=\"\"; filename="."\"test1.txt\""."\r\nContent-Type: ".$type."\r\n\r\n".$contents."\r\n\r\n--".$random_hash;
    
    $request = $request_pre; //nl2br($request_pre);
    
    $length=strlen($request);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("HTTP/1.1", "Content-Type: multipart/mixed; boundary=".$random_hash));
    curl_setopt($ch, CURLOPT_URL,$target_url); 
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST,1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $request); 
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLINFO_HEADER_OUT, true); 
    $response = curl_exec($ch);
    

    Just to note that I have found working with PHP Curl to be less than desirable. Consider using the HTTPRequest package.