Challenge:
Before few weeks back, was working on a task where we needed to add media file programmatically and that too language specific.
You may ask why we need to do so. Really a good question, Here’s the answer for the same: Let’s say for an example you have a product, and each product will have a USER Guide and user guide may exist in each language. So, rather than creating different media item for each language specific user guide, we wanted to have only one media item and language specific different file.
Solution:
Adding media file programmatically is pretty much straight forward task with Sitecore API, and following are the best resources on the web which helps us to do so:
But to add language specific media item programmatically, We haven’t found anything already written on the web. After that we did a bit of a research and invested good amount of time to make it happen. And thought to share with you with the hope that you no need to invest same time again.
To make it happen tried following approach first while creating file programmatically:
// Do not make a versioned template
options.Versioned = true;
// Language added
options.Language = language; // Language Instance gets passed to us
To test it, we iterate the loop twice, Where in first Iteration we create media item in en language and in second iteration we create media item in another language. Let’s say es-ES. But the later iteration overrides the first version. We also tried with options.KeepExisting = true; But with no luck 😦
Good to read : http://learningsitecorecms.blogspot.in/2013/09/sitecore-media-item-created-in-multiple.html
Then did a quick search on Google and SDN. But unfortunately couldn’t find anything which instructs us to do so. But at the same time found this nice article [Login Required] : http://sdn.sitecore.net/snippets/item%20handling/media%20library/updating%20image%20file%20on%20a%20media%20library%20item%20programmatically.aspx
And changed code like this:
MediaItem mediaItem = (MediaItem)database.GetItem(options.Destination, <strong>language</strong>);
if (mediaItem == null)
{
// Now create the file in Sitecore. Using Static options
mediaItem = Sitecore.Resources.Media.MediaManager.Creator.CreateFromStream(memoryStream, fileName, options);
}
else
{
Sitecore.Resources.Media.Media media = MediaManager.GetMedia(mediaItem);
media.SetStream(memoryStream, ".pdf"); // Hard coded for simplicity
}
Here we are checking that if Media Item already exist then add language specific media version. And it worked!
Full Code:
/// <summary>
/// This method will be used to add file in
/// Sitecore Media Library folder
/// </summary>
/// <param name="fileName">Full Name of file</param>
/// <param name="sitecorePath">Sitecore Path</param>
///mediaItemName">Name of media item
/// <returns>Newly created media item</returns>
public static Item AddFile(string fileName, string sitecorePath, string mediaItemName, Stream responseStream, Database database, Sitecore.Globalization.Language language)
{
// Create the options
Sitecore.Resources.Media.MediaCreatorOptions options = new Sitecore.Resources.Media.MediaCreatorOptions();
// Store the file in the database, not as a file
options.FileBased = false;
// Remove file extension from item name
options.IncludeExtensionInItemName = false;
// Overwrite any existing file with the same name
//options.KeepExisting = false;
// Do not make a versioned template
// Set it as per your need - if you are going to use same method
// Make it parametrized
options.Versioned = true;
// Language added
options.Language = language;
// set the path
options.Destination = sitecorePath + "/" + mediaItemName;
// Set the database
options.Database = database;
// Now create the file
//Sitecore.Resources.Media.MediaCreator creator = new Sitecore.Resources.Media.MediaCreator();
//MediaItem mediaItem = creator.CreateFromFile(fileName, options);
// Read the file from stream:
MemoryStream memoryStream = new MemoryStream();
/* This approach throws an error "This stream does not support seek operations."
* While using Response Stream. So, following approach works with FileStream as well
as HttpWebResponseStream
memoryStream.SetLength(fileStream.Length);
fileStream.Read(memoryStream.GetBuffer(), 0, (int)fileStream.Length);
memoryStream.Flush();
*/
byte[] buffer = new byte[2048];
int bytesRead = 0;
do
{
bytesRead = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
responseStream.Close();
memoryStream.Flush();
/*
*
Added SetStream Code as there is no such way using which Sitecore's API
will create language specific version directly, It used to overwrite
* the last upload operation. Which means at one time only one language
* version was getting uploaded
*/
MediaItem mediaItem = (MediaItem)database.GetItem(options.Destination, language);
if (mediaItem == null)
{
// Now create the file in Sitecore. Using Static options
mediaItem = Sitecore.Resources.Media.MediaManager.Creator.CreateFromStream(memoryStream, fileName, options);
}
else
{
// Attach Version specific media item
Sitecore.Resources.Media.Media media = MediaManager.GetMedia(mediaItem);
media.SetStream(memoryStream, Path.GetExtension(fileName));
}
memoryStream.Dispose();
return mediaItem;
}
Just a note: We confirmed this approach with Sitecore support and they are fine with it!
Happy Language Specific Media Creation! 🙂