1

I have two ajax calls below. First to get the contents of a document on my server into an arraybuffer. Then a second call to a Flow to add the file contents into a new file on SharePoint.

This works fine for other file types, like .txt, but for .docx I get corrupted files. Does anybody know how to do this for .docx files?

javascript.js

function uploadfile(){
    var filename = "Doc1.docx"
    $.ajax({
        method: 'GET',
        dataType: 'native',
        url: "temp/"+filename,
        xhrFields: {
            responseType: 'arraybuffer'
        },
        ContentType: "application/octet-stream",
        success: function(arraybuffer){
            console.log(arraybuffer);
            arraybuffer = String.fromCharCode.apply(null, new Uint8Array(arraybuffer));
            console.log(arraybuffer);
            var requestdigest = getrequestdigest();
            $.ajax({
                //Flow Http Request to upload file from server
                url: "https://prod-33.westus.logic.azure.com:443/workflows/WORKFLOWID/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=SIGNATURE",
                method: 'POST',
                headers: {
                    "Content-Type": "application/json;charset=UTF-8"
                },
                processData: false,
                data: JSON.stringify({
                    'content': arraybuffer,
                    'name': filename,
                    'requestdigest': requestdigest
                })
            }).done(function(item){
                console.log("SUCCESS "+JSON.stringify(item));
            }).fail(function(error){
                console.log("ERROR "+JSON.stringify(error));
            });
        }
    });
}

Flow to upload document

0

Here is the solution. The below retrieves the contents of a .docx file. My PHP does a search and replace to modify the .docx file before returning the contents. The PHP converts the contents to Base64. The JavaScript then converts this to a blob. Then the Flow accepts the content and runs the SharePoint "Create file" step, successfully creating an uncorrupted .docx file on the SharePoint.

javascript.js

function uploadfile(){
    $.ajax({
        method: 'POST',
        dataType: 'native',
        url: "generatetemplate.php",
        ContentType: "application/octet-stream",
        data: JSON.stringify({
        }),
        success: function(blob){
            console.log(blob);
            var requestdigest = getrequestdigest();
            var filename = "Test.docx";
            blob = "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,"+blob;
            $.ajax({
                //Flow Http Request to upload file from local drive
                url: "https://prod-33.westus.logic.azure.com/workflows/XXXXXXXXXXXXXXXXXXXXX/triggers/manual/paths/invoke/"+filename+"?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=XXXXXXXXXXXXXXXXXXXXXX",
                method: 'POST',
                ContentType: "octet-stream",
                processData: false,
                data: makeblob(blob)
            }).done(function(item){
                console.log("SUCCESS "+JSON.stringify(item));
            }).fail(function(error){
                console.log("ERROR "+JSON.stringify(error));
            });
        }
    });
}
makeblob = function (dataURL) {
    var BASE64_MARKER = ';base64,';
    if (dataURL.indexOf(BASE64_MARKER) == -1) {
        var parts = dataURL.split(',');
        var contentType = parts[0].split(':')[1];
        var raw = decodeURIComponent(parts[1]);
        return new Blob([raw], { type: contentType });
    }
    var parts = dataURL.split(BASE64_MARKER);
    var contentType = parts[0].split(':')[1];
    var raw = window.atob(parts[1]);
    var rawLength = raw.length;
    var uInt8Array = new Uint8Array(rawLength);
    for (var i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], { type: contentType });
}

generatetemplate.php

<?php
    function runCurl($url, $post = null, $headers = null, $action = null) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, $post == null ? 0 : 1);
        if($post != null) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        }
        if($action!=null){curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $action);}
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if($headers != null) {
            curl_setopt($ch, CURLOPT_HEADER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return $response;
    }
    $headers = array(
        "Content-Type: application/json;odata=verbose",
        "Accept: application/json;odata=verbose",
        "Content-Length: 0"
    );
    $data = array("path" => "Test/Test.docx");
    $body = json_encode($data);
    //Flow Http request to get template file .docx file from SharePoint
    $response = runCurl('https://prod-49.westus.logic.azure.com:443/workflows/XXXXXXXXXXXXX/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=XXXXXXXXXXXXX', $body, $headers, "POST");
    $pks = explode("\r\n\r\n",$response);
    $pk = $pks[1];
    file_put_contents("temp/test.docx",$pk); //Save it on the server

    $zip_val = new ZipArchive;
    //Docx file is nothing but a zip file. Open this Zip File
    $pk=file_get_contents("temp/test.docx");
    if($zip_val->open("temp/test.docx") == true){
        $key_file_name = 'word/document.xml';
        $message = $zip_val->getFromName($key_file_name);
        $timestamp = date('d-M-Y H:i:s');
        // this data Replace the placeholders with actual values
       $message = str_replace("timestamp", $timestamp, $message); //Replace string 'timestamp' with the current timestamp variable
        //Replace the content with the new content created above.
        $zip_val->deleteName($key_file_name);
        $zip_val->addFromString($key_file_name,$message);
        $zip_val->close();
        $pk=file_get_contents("temp/test.docx");
        $pk = base64_encode($pk);    //Encode the file binary content in base64
        echo $pk; //Echo the base64 content back to the Ajax call in javascript.js
    } else{
        echo("false");
    }
?>

Microsoft Flow

The Compose step below is critical. The Input field is filled with "@{triggerBody()['$content']}" minus the quotation marks.

Flow

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.