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.