How to copy file using Rest API and javascript in

2020-07-17 06:46发布

问题:

I need to copy file between document libraries. Library A is located in one site and Library B is located in subsite. I know how to copy file between libraries on the same level but the problem is with copying between different level.

The code I use to copy file between libraries on the same level.

 $.ajax({
     url : "http://xxx/PWA/_api/web/folders/GetByUrl('/PWA/CopyFromLibrary')/Files/getbyurl('Import.csv')/copyTo(strNewUrl = '/PWA/TargetLibrary/Import.csv',bOverWrite = true)",

method: 'POST',
    headers: {
        "Accept": "application/json; odata=verbose",
        "X-RequestDigest":  $("#__REQUESTDIGEST").val()
    },
    success: function () {
        alert("Success! Your file was copied properly");
    },
    error: function () {
        alert("Problem with copying");
    }
    });

For different level I use just another target URL:

url : "http://xxx/PWA/_api/web/folders/GetByUrl('/PWA/CopyFromLibrary')/Files/getbyurl('Import.csv')/copyTo(strNewUrl = '/PWA/Subsite/TargetLibrary/Import.csv',bOverWrite = true)",

And it doesn't work. How to work around this problem?

回答1:

Just figured this one out today for the cross site solution. The trick is-- don't use $.ajax for the download of the document. Use good old XMLHttpRequest. The reason is that JQuery simply doesn't let you get a raw binary data array from SharePoint. But, the XMLHttpRequest does because it allows you to get an arraybuffer as part of its implementation, which SharePoint accepts!

The following is the code with the parts identified for building the full source and target REST urls. Note that you can use $.ajax to upload the file.

  • sourceSite is a sharepoint site suitable for appending the '_api' rest endpoint
  • sourceFolderPath is the relative folder path your document is located within
  • sourceFileName is the filename of the document
  • targetSite, targetFolderPath and targetFileName are the mirror images or source, only for the destination.
  • requestDigest is that special value you need for SharePoint to accept updates.

    function copyDocument(sourceSite, sourceFolderPath, sourceFileName, targetSite, targetFolderPath, targetFileName, requestDigest) {
    
        var sourceSiteUrl = sourceSite + "_api/web/GetFolderByServerRelativeUrl('" + sourceFolderPath + "')/Files('" + sourceFileName + "')/$value";
        var targetSiteUrl = targetSite + "_api/web/GetFolderByServerRelativeUrl('" + targetFolderPath + "')/Files/Add(url='" + targetFileName + "',overwrite=true)";
    
        var xhr = new XMLHttpRequest();
        xhr.open('GET', sourceSiteUrl, true);
        xhr.setRequestHeader('binaryStringResponseBody', true);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function (e) {
            if (this.status == 200) {
                var arrayBuffer = this.response;
                $.ajax({
                    url: targetSiteUrl,
                    method: 'POST',
                    data: arrayBuffer,
                    processData: false,
                    headers: { 'binaryStringRequestBody': 'true', 'Accept': 'application/json;odata=verbose;charset=utf-8', 'X-RequestDigest': requestDigest }
                })
                .done(function (postData) {
                console.log('we did it!');
                })
                .fail(function (jqXHR, errorText) {
                console.log('dadgummit');
            });
            }
        }
        xhr.send();
    }
    


回答2:

What kind of error are you getting?

One probable cause of your problem is that your RequestDigest does not match the location where you want to POST your file since it is fetched from the page where your code is running. Fetch a matching RequestDigest by calling '_api/contextinfo' on your target location.

See: http://blogs.breeze.net/mickb/2012/11/20/SP2013GettingAFormDigestForUpdateRESTCalls.aspx and http://msdn.microsoft.com/en-us/magazine/dn198245.aspx (writing to Sharepoint section)



回答3:

Note File Move operations only work within the scope of a given document library. You cannot copy between document libraries.

http://msdn.microsoft.com/en-us/library/office/dn605900(v=office.15).aspx#Folder6



回答4:

For POST - operation we need request digest value, which is used by SharePoint to authenticate mainly for Post, Delete, Update not needed for GET operation, Sample jquery ajax code for post operation-

 $.ajax({
        url: url + "/_api/web/lists/getbytitle('" + listname + "')/items",
        type: "POST",
        contentType: "application/json;odata=verbose",
        data: JSON.stringify(item),
        headers: {
            "Accept": "application/json;odata=verbose",
            "X-RequestDigest": $("#__REQUESTDIGEST").val()
        },
        success: function (data) {
            success(data); // Returns the newly created list item information
        },
        error: function (data) {
            failure(data);
        }
    });


回答5:

You can try the following code for copying file from one location to another within SharePoint.

The following example will be helpful in copying files within SharePoint sandbox.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myapp" ng-controller="mycont">
    <input type="button" ng-click = "myclick()" value="Angular File Copy" />    
</div>

<input type=button onclick="x()"  value="jQueryFile copy" />
<script>
    var dt =new Date();
    var val_ue = dt.getDate()+""+dt.getHours()+""+dt.getMinutes()+""+dt.getSeconds() +"1" ;
    var url1 = "/_api/web/getfilebyserverrelativeurl('/Lists/Document_Mapping/Attachments/1/9.jpg')";
    var url2 = "/Lists/AddressVersioning/Attachments/84/" ;
    var combined = "";
    var app = angular.module('myapp',[]);
    var _headers = {
        'X-RequestDigest': document.getElementById("__REQUESTDIGEST").value,
        'accept':'application/json;odata=verbose'
    };
    app.controller('mycont',function($scope,$http){
        $scope.myclick =  function(){
            combined = url1 + "/copyTo('" + url2 + val_ue + ".jpg')";
            $http({method:'POST',url:combined,headers:_headers}).then(
                function(response){
                    console.log("hi");
                    val_ue += 1;
                },
                function(error){
                    console.log("Error:");
                    console.log(error);
                },
                function(process){
                    console.log("process:");
                    console.log(process);
                }
            );
        }
    });
    var x = function(){
        combined = url1 + "/copyTo('" + url2 + val_ue + ".jpg')";
        $.ajax({
            url : combined,
            method: 'POST',
            headers: {
                "Accept": "application/json; odata=verbose",
                "X-RequestDigest":  $("#__REQUESTDIGEST").val()
            },
            success: function () {
                alert("Success! Your file was copied properly");
                val_ue +=1;
            },
            error: function () {
                alert("Problem with copying");
            }
        });
    }
</script>

Note: the above function will not work if the list item is newly created. But for all other situations it will work (even form one doc library to another doc library or cross site / site collection)