CopyTo List Attachment to Shared Documents

As part of one of my projects at work, I was tasked to modify a form for a list to have the Attachment moved to the Document Library. When the file is in the Document Library, I can then apply all sorts of change control and stuff to the document. Being new to playing around with jQuery and JSOM in SharePoint, I searched the web for an example on how to do this action. I found that there was a method called copyTo that would do what I needed. Great! Now how do I use it?

I searched around and even found a site that said

Note: If you want to copy files between two libraries on the same level, then you can use the copyTo method.

http://server/site/_api/web/folders/GetByUrl('/site/srclib')/Files/getbyurl('madcow.xlsx')/copyTo(strNewUrl = '/site/targetlib/madcow.xlsx,bOverWrite = true)

Okay, that seems pretty straight forward and not informative enough. I even tried to look at his code for copying to a different site to see if a light bulb would go off in my head. Looking on SharePoint StackExchange wasn’t yielding any positive results, so I posted a question myself (Forbidden error when trying to copyTo document from list to Document Library) when attempts to get the coding to work kept failing. As with all road blocks, the best option is to step back, go do something else to clear your head and then come back to the problem.

I (by accident) deleted all my saved tabs in my browser, so I had to do a new search to find the pages I had up. When I did this search, I found a question in SharePoint StackExchange; Automatically add attachment to new list item. At first I didn’t think it would help me, but then after looking at it for a while, I decided to give it a try. I ended up getting a better error and then, presto!! It worked! Woo hoo!

So, that I can find this for later and hopefully help someone else out, I am going to post the answer here and on the StackExchange.

Note: The getUrlParameter(“ID”) is a short function that splits out the page URL and retrieves the value for the parameter. Someone else created it and it works perfectly.

	function getQueryStringParameter(paramToRetrieve) {
		var params = document.URL.split("?")[1].split("&");
		var strParams = "";

		for (var i = 0; i < params.length; i = i + 1) {
		  var singleParam = params[i].split("=");
		  console.info("singleParam : " + singleParam);
		  if (singleParam[0] == paramToRetrieve)
			return singleParam[1];
		}
	}

First, create the function to get the current list and current item in order to find the attachment as the file object.

    function justCopyIt() {
    		thisClientContext = new SP.ClientContext.get_current();
    		this.web = thisClientContext.get_web();
    		this.sourceList = this.web.get_lists().getByTitle("Memo");
    		thisClientContext.load(this.sourceList);
    		this.currentItem = sourceList.getItemById(getUrlParameter("ID"));
    		thisClientContext.load(this.currentItem);

    		var attachmentFolder = this.web.getFolderByServerRelativeUrl("/sites/MySite/Lists/Memo/Attachments/" + getUrlParameter("ID") + "/");
    		sourceFile = attachmentFolder.get_files();

    		thisClientContext.load(sourceFile);
    		thisClientContext.executeQueryAsync(Function.createDelegate(this, onQuerySucceeded), Function.createDelegate(this, onGetFail));
    	}

After the source file is loaded, call the executeQueryAsync to run the query.
I have a onGetFail function that I handle all failed query calls. Don’t forget to create one of your own.

    function onQuerySucceeded(sender, args) {
    		if (sourceFile != null) {

    			destinationlibUrl = "http://myServer/sites/MySite/Shared%20Documents/" + $.local.arrFileName;
    			sourceFile.itemAt(0).copyTo(destinationlibUrl, 1);

    			notifyId = SP.UI.Notify.addNotification("Copying file " + sourceFile.itemAt(0).get_serverRelativeUrl() + " to " + destinationlibUrl, true);
    			thisClientContext.executeQueryAsync(
    				function (sender, args) {
    					SP.UI.Notify.removeNotification(notifyId);
    					SP.UI.Notify.addNotification('File copied successfully', true);
    				},
    				function (sender, args) {
    					 SP.UI.Notify.addNotification('Error copying file', false);
    					 SP.UI.Notify.removeNotification(notifyId);
    					 console.error('Error occured: ' + args.get_message());
    				}
    			);
    		}
    	}

When the onQuerySucceed function runs, it does the copyTo and adds a on screen notification to let the user know the “Copying File” has started and when it is successful.

Seems so simple when it works.

About DeanLogic
Dean has been playing around with programming ever since his family got an IBM PC back in the early 80's. Things have changed since BASICA and Dean has dabbled in HTML, JavaScript, Action Script, Flex, Flash, PHP, C#, C++, J2ME and SQL. On this site Dean likes to share his adventures in coding. And since programming isn't enough of a time killer, Dean has also picked up the hobby of short film creation.

About DeanLogic

Dean has been playing around with programming ever since his family got an IBM PC back in the early 80's. Things have changed since BASICA and Dean has dabbled in HTML, JavaScript, Action Script, Flex, Flash, PHP, C#, C++, J2ME and SQL. On this site Dean likes to share his adventures in coding. And since programming isn't enough of a time killer, Dean has also picked up the hobby of short film creation.