0

I am performing a "GET" request for a file on my SharePoint site because I need to be able to copy a list item and then copy each of its attachments. I am able to use this code to get the associated binary of many other files (at least one is an excel file, but I'm not sure all excel files have this issue).

The error generated in IE is :

Could not complete the operation due to error c00ce514

whereas FireFox provides a long string which looks like corrupted binary. It looks like I'm having this issue for word docs (.doc and .docx) and excel files. I suspect this is this case with all office products at the moment. PDFs, text files, and all images that I've tested so far have worked 100% of the time. The error changes depending on what I set as the content-type or dataType. What could be causing this? Is this because SharePoint changes the content of your uploaded word/excel files?

Sample:

   $.ajax({
                async: false,
                cache: false,
                type: "GET",
                header: {"content-type": "text/html; charset=windows-1251"},
                url: attachments[i] //e.g., blah.com/mytext.txt or ../myPic.png
                }).done(function(result){
     }).fail(function(error)){
         console.log(JSON.stringify(error)); //this is where I see the two error types that change depending on my browser.
    });

Update: More info below trying a different method:

$.ajax({
                async: false,
                cache: false,
                type: "GET",
                /*headers: {
                    "content-type": "text/plain"
                    //"content-type": "text/html; charset=windows-1251"
                },
                url: attachments[i]*/
                url: hostURL + "/_api/web/GetFileByServerRelativeUrl('" + attachments[i] + "')/$value?",
                binaryStringResponseBody: true,
            }).done(function (result) {  //got binary.. add attachment..
                var _url = hostURL + "/_api/web/lists('" + listID + "')/items(" + newItemID + ")/AttachmentFiles/add(FileName='"
                    + decodeURIComponent(attachments[i].split("/").pop()) + "')";
                $.ajax({
                    url: _url,
                    async: false,
                    cache: false,
                    type: "POST",
                    data: result,
                    headers: {
                        "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                        "accept": "application/json;odata=verbose"
                    }
                }).done(function (data) { //redirect if this is the last attachment
                    console.log("success on the index" + attachments[i]);
                    if (i == attachments.length - 1) {
                        window.location.href = hostURL + "/Lists/Summary Documents/UpdateForm.aspx?ID=" + newItemID + "&RefID=" + refID;
                    }
                }).fail(function (error) {
                    console.log("error on: " + attachments[i]);  //error adding attachment
                    alert(JSON.stringify(error));
                });
            }).fail(function (error) {
                console.log("Error getting the attachment.");
                console.log(error);
                alert(JSON.stringify(error)); //error getting attachment
            })

^ changing my "GET" prevented the code from hitting the fail promise ("Error getting the attachment") but the created file is now corrupt for all files, including the PDFs which previously worked.

  • Are there any resources anywhere that would help me from even a beginning standpoint? It doesn't seem like I'm getting this error on non-SP sites :( – Dinerdo Sep 10 '15 at 21:06
  • Have you tested experimenting with the accept header? Also Content-Type Header could be a problem here. – Nils Sep 14 '15 at 7:01
  • Did you try SharePoint REST api to download file?. A similar question here. sharepoint.stackexchange.com/questions/72511/… – sekhar Sep 14 '15 at 8:01
  • I have tried experimenting with the header. I've tried plain text and whatnot. I just feel like I'm guessing because I'm not finding a good online reference for what I should be trying specifically. – Dinerdo Sep 14 '15 at 18:23
1
+50

After numerous attempts at trying to do this using jQuery, I finally managed to get this working using SP.RequestExecutor thanks to Mikael Svenson's excellent post here.

There's some encoding problem with jQuery $.ajax which makes it omit some bytes (hence the problem of your file getting corrupted). In several tests, I always found the length of the binary response I got after fetching getfilebyserverrelativeurl()/openbinarystream using jQuery was around a ~100 bytes lesser than what I got by using CSOM (C#) and the REST api endpoint (getfilebyserverrelativeul()/length.

I then stumbled upon Mickael's solution using SP.RequestExecutor which worked properly.

Code is as below. I have hardcoded the URLs for attachments which you'll have to change. I've tested the below solution with .docx, .pdf, .xlsx, .jpg and with all, it works.

$(document).ready(function(){  

//fix for requestexecutor bug as mentioned in Mikael's post - begin

$.getScript("siteUrl/_layouts/15/SP.RequestExecutor.js", function(){
SP.RequestExecutorUtility.IsDefined = function SP_RequestExecutorUtility$$1(data) {
   var nullValue = null;
   return data === nullValue || typeof data === 'undefined' || !data.length;
};
SP.RequestExecutor.ParseHeaders = function SP_RequestExecutor$ParseHeaders(headers) {
   if (SP.RequestExecutorUtility.IsDefined(headers)) {
  return null;
   }
   var result = {};
   var reSplit = new RegExp('\r?\n');
   var headerArray = headers.split(reSplit);
   for (var i = 0; i < headerArray.length; i++) {
      var currentHeader = headerArray[i];
   if (!SP.RequestExecutorUtility.IsDefined(currentHeader)) {
     var splitPos = currentHeader.indexOf(':');

     if (splitPos > 0) {
        var key = currentHeader.substr(0, splitPos);
        var value = currentHeader.substr(splitPos + 1);

        key = SP.RequestExecutorNative.trim(key);
        value = SP.RequestExecutorNative.trim(value);
        result[key.toUpperCase()] = value;
     }
  }
}
return result;
};
SP.RequestExecutor.internalProcessXMLHttpRequestOnreadystatechange = function SP_RequestExecutor$internalProcessXMLHttpRequestOnreadystatechange(xhr, requestInfo, timeoutId) {
   if (xhr.readyState === 4) {
  if (timeoutId) {
     window.clearTimeout(timeoutId);
  }
  xhr.onreadystatechange = SP.RequestExecutorNative.emptyCallback;
  var responseInfo = new SP.ResponseInfo();

  responseInfo.state = requestInfo.state;
  responseInfo.responseAvailable = true;
  if (requestInfo.binaryStringResponseBody) {
     responseInfo.body = xhr.response; 
  }
  else {
     responseInfo.body = xhr.responseText;
  }
  responseInfo.statusCode = xhr.status;
  responseInfo.statusText = xhr.statusText;
  responseInfo.contentType = xhr.getResponseHeader('content-type');
  responseInfo.allResponseHeaders = xhr.getAllResponseHeaders();
  responseInfo.headers = SP.RequestExecutor.ParseHeaders(responseInfo.allResponseHeaders);
  if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 1223) {
     if (requestInfo.success) {
        requestInfo.success(responseInfo);
     }
  }
  else {
     var error = SP.RequestExecutorErrors.httpError;
     var statusText = xhr.statusText;

     if (requestInfo.error) {
        requestInfo.error(responseInfo, error, statusText);
     }
  }
}};

//fix - end. Calling function to get binary from file

executorTry();
});
});

//function to upload the file using arraybuffer fetched in executorTry()
function saveBinary(arrayBuffer)
{
        var _url = "http://siteUrl/_api/web/lists/getbytitle('Business Units')/items(1)/AttachmentFiles/add(FileName='test.pdf')";
            $.ajax({
                url: _url,
                async: false,
                cache: false,
                type: "POST",
                data: arrayBuffer,
                processData:false,
                headers: {
                    "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                    "accept": "application/json;odata=verbose"
                }
            }).done(function (data) { //redirect if this is the last attachment
                console.log("success on the index");
            }).fail(function (error) {
                console.log("error on: " + attachments[i]);  //error adding attachment
                alert(JSON.stringify(error));
            });

}

//function to get the binary using requestexecutor
function executorTry()
{
          var fileContentUrl = "http://siteUrl/_api/web/getfilebyserverrelativeurl('/Lists/testlist/Attachments/4/test.pdf')/openbinarystream";
          var executor = new SP.RequestExecutor("siteUrl");
          var info = {
            url: fileContentUrl,
            method: "GET",
            binaryStringResponseBody: true,
            success: function (data) {
            //binary data available in data.body. Passing the ArrayBuffer to saveBinary method.
            saveBinary(data.body);
          },
          error: function (err) {
          alert(JSON.stringify(err));
          }
          };
          executor.executeAsync(info);
}

Hope this helps!

0

You have to add binaryStringResponseBody: true, parameter

var info = {
        url: appwebUrl + "/_api/SP.AppContextSite(@target)/web/GetFileByServerRelativeUrl('/sites/Test/Shared Documents/" + sourcefile.get_name() + "')/$value?@target='myhosturl'",

        binaryStringResponseBody: true,
        success: function (data) {
        },
        error: function () { alert('error'); }

    }

in msdn, you can find binaryStringRequestBody: true for adding file to Document library. Similarly you can add binaryStringResponseBody: true

  • Have you tried this on a list item attachment? This didn't seem to fix the issue. – Dinerdo Sep 14 '15 at 15:56
  • I added more info in my question. binaryStringResponse and Request seem to make the "GET" go through, but the file is created incorrectly. – Dinerdo Sep 14 '15 at 18:27

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.