Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more

How to move media file from one asset folder to another programatically?

Vote:
 

I have two media folders - upload and archive. There is a job running in the system processes the file that user uploads in the upload folder. Once it's complete, it needs to move the file to the  archive folder.

I can retrieve all the files from the upload folder and process it programatically, but I don't have any clue how to link the processed file to archive folder, can some one provide a code sample?

thanks

#86554
May 23, 2014 14:03
Vote:
 
var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
var repository = ServiceLocator.Current.GetInstance<IContentRepository>();
var archiveFolderRef = <%YourContentRefToArchiveFolder%>
var folder = repository.GetDefault<ContentAssetFolder>(archive);

foreach(var fileRef in fileRefs)
{
	var mediaFile = repository.Get<MediaData>(fileRef)
	folder.Attach(mediaFile);
}

repository.Save(folder, SaveAction.Publish);
#86555
May 23, 2014 14:17
Vote:
 

I tried similiar code this afternoon, but I kept getting the following errors

"The specified content does not implement IResourcable and hence it cannot have a content asset folder"

#86562
May 23, 2014 15:35
Vote:
 

Hi Petter

I reflected into MediaData source code, and I saw the MediaData didn't not implement the IResource interface, therefore folder.Attach method gets called, it throws that exception.

public virtual void Attach(IContent content)
{
    Validator.ThrowIfNull("content", content);
    IResourceable resourceable = content as IResourceable;
    if (resourceable == null)
    {
        throw new ArgumentException("The specified content does not implement IResourcable and hence it cannot have a content asset folder");
    }
    if ((this.ContentGuid == Guid.Empty) || (content.ContentGuid == Guid.Empty))
    {
        throw new InvalidOperationException("Both content and ContentAssetFolder must have values assigned for ContentGuid before they can be attached");
    }
    if (string.IsNullOrEmpty(this.Name))
    {
        this.Name = content.Name;
    }
    resourceable.ContentAssetsID = this.ContentGuid;
    this.ContentOwnerID = content.ContentGuid;
}

 

 
  public virtual void Attach(IContent content)
{
    Validator.ThrowIfNull("content", content);
    IResourceable resourceable = content as IResourceable;
    if (resourceable == null)
    {
        throw new ArgumentException("The specified content does not implement IResourcable and hence it cannot have a content asset folder");
    }
    if ((this.ContentGuid == Guid.Empty) || (content.ContentGuid == Guid.Empty))
    {
        throw new InvalidOperationException("Both content and ContentAssetFolder must have values assigned for ContentGuid before they can be attached");
    }
    if (string.IsNullOrEmpty(this.Name))
    {
        this.Name = content.Name;
    }
    resourceable.ContentAssetsID = this.ContentGuid;
    this.ContentOwnerID = content.ContentGuid;
}

 
#86568
May 23, 2014 16:23
Vote:
 

Hmm didn't have time to try my code while at work. And after playing some at home I still can't find a way to move the file. But I found a workaround.

The following code works in the alloy templates.

var contentAssetFolder = _contentRepository.Get<ContentFolder>(SiteDefinition.Current.SiteAssetsRoot);
var images = _contentRepository.GetChildren<ImageFile>(contentAssetFolder.ContentLink);
var folders = _contentRepository.GetChildren<IContent>(SiteDefinition.Current.SiteAssetsRoot);

foreach (var item in folders)
{
	if (item.Name == "Events")
	{
		var folder = item;
		ImageFile image = images.First() as ImageFile;
		var newFile = _contentRepository.GetDefault<ImageFile>(item.ContentLink);
		newFile.Name = image.Name;
		newFile.BinaryData = image.BinaryData;
		
		_contentRepository.Save(newFile , SaveAction.Publish);
		_contentRepository.Delete(image.ContentLink, true);
	}
}

Here I take the first file in the root folder and then find the Events folder and create a new item in it. Then set the new item to the same binarydata as the old one and save it. Then remove the old one.

Not the way I would want to do it but the only way I could figure out.

Tried with:

if (item.Name == "Events")
{
	var folder = item;
	ImageFile image = images.First().CreateWritableClone() as ImageFile;
	image.ParentLink = folder.ContentLink;
	_contentRepository.Save(image , SaveAction.Publish);
}

But that didn't work. So you could use the first snippet in wait for someone more in the know showing us how it's done =)

#86574
May 23, 2014 21:30
Vote:
 

how about 

_contentRepository.Move(mediaContentLink, destinationContentLink);



#86627
May 27, 2014 9:13
Vote:
 

Hahaha way to easy ;)

Thanks Per. Most have been tired when checking the API.

#86628
May 27, 2014 9:31
Vote:
 

Hehe, no problem.

Quick tip: If you need to find content matching a name, instead of using .GetChildren, looping through and checking for a matching name, you could instead do:

_contentRepository.GetBySegment(destinationContentLink, "events", null);
#86631
May 27, 2014 9:43
Vote:
 

Grand thanks.

#86634
May 27, 2014 10:03
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.