3

I'm trying to build a the following functionality into a library view:

  • Each document has a checkbox beside it
  • User checks off which documents/folders they want to copy
  • User clicks a "Copy Files" button at the top of the view
  • Script then copies each file or folder from the current library to a fixed location elsewhere on the site

The script & process works great on files but burps when it hits a folder. After adding logging, it appears to be returning the proper server relative URL for the folder but then errors out when I call the CopyTo method. After a few days of digging around & googling, I'm coming to the conclusion that CopyTo only works with files, not folders.

Is this true? And if so, what is the proper way to copy a folder using REST and JavaScript?

Note: I haven't posted my code, since the question is more about REST functionality than my actual script. If needed, however, I can post my script. It's based on the one from here.

2 Answers 2

6

There's no easy way to do it, but nothing stops you from manually checking if the folder exists and then adding it if you need to, then copying files from inside to the new one:

You can check if a list item is a folder by checking its content type (folders will be "Folder")...

To get the content type you need to select and expand ContentType on each item with a URI like this:

_api/web/lists/getbytitle('Documents')/Items(7)?select=Title,ContentType&$expand=ContentType

Then you can use data.ContentType.Name to get the name of the content type

I'll also throw in here that if you just don't want to support copying folders and don't want your script to die, you can just tell the user they selected a folder by checking the item's content type like this and suggesting they only pick files

...If you decide you do want to implement though, you can create a folder using the REST API like this:

function createFolderAsync(newFolderSiteRelativeUrl) {
    var reqData = JSON.stringify({ '__metadata': { 'type': 'SP.Folder' }, 'ServerRelativeUrl': newFolderSiteRelativeUrl });
    return $.ajax({
        url: "../_api/web/folders",
        type: "POST",
        data: reqData,
        headers: {
            "accept": "application/json;odata=verbose",
            "content-type": "application/json;odata=verbose",
            "X-RequestDigest": $('#__REQUESTDIGEST').val(),
        }
    });
}

(function () {
    $('#yourButton').click(function() {
        createFolderAsync('Shared Documents/restTest').done(function () {
            console.log('do some other stuff now...');
        }).fail(function (jqXHR) {
            console.log(jqXHR.responseText);
        });
    })
}());

It doesn't seem to matter if you 'create' a folder that already exists, it doesn't overwrite existing stuff.

A note on the new folder url: as explained in an answer from Vadim on this question, you'll need to use the right URL path for the folder (and not, for example, the internal library name where you want to add it).

Then you would need to go get all the files in that folder (and maybe the other folders recursively?) and copy them to the new destination...

I would just alert the user they can't pick folders and leave it at that, but I see you already had that battle! :) At the very least you should let them know the time cost for doing this instead of other things.

3
  • This sounds like the way I might go. Unfortunately I already had the "No folders" argument with the business unit and lost. What I can probably do is create the folder using the Add method you mentioned, then for each item in the folder I'll just call my working CopyFile function. Do you know of somewhere I can find some real-life examples of calling the method? MSDN just has basic placeholder info and so far all of my google results are coming back with C# in VS projects instead of javascript.
    – Omegacron
    Commented Jul 28, 2014 at 21:18
  • 2
    @Omegacron Okay edited and put in some working samples for you using JS -- I don't know how familiar you/your team are with REST vs the JavaScript Object Model, but you would probably gain a lot of advantages with batching using the JSOM. But - I get people do different stuff, that's why there are multiple ways in.
    – John-M
    Commented Jul 29, 2014 at 2:36
  • I didn't use this exact code, but it got me thinking in the right direction and I was able to get going with something similar. Thanks - marked as answer!
    – Omegacron
    Commented Aug 4, 2014 at 17:24
0

CopyTo does not appear to be supported for folders in the REST API. See the Folder Methods section of Files and folders REST API reference

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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