The SDL Tridion CMS uses a special kind of object called a Multimedia Component to store binary files managed by a CMS use. Typical uses for these MM Components are images, office documents, pdfs etc. In older additions of SDL Tridion, these were rendered/published by VBScript or XSLT templates using a method called PublishBinary().

The PublishBinary() method did two things. Firstly it extracted the binary file from the CMS, and  prepared it for deployment to the presentation server (essentially took the blob from the DB, and created a file from it, and placed it in the Publish Transaction zip file). Secondly, it returned the location that the file would be placed in once it was published. This value could then be used by your template to create HTML links to your binary files.

This approach worked well, except that all of the binaries were placed in one directory on the web server, which might have led to unique naming issues. To get around this problem, the PublishBinary() method would add a unique suffix (based on the MM Components URI) to the file name of the published file.

E.g. A multimedia component containing a file named "stuff.png", with a URI of "tcm:35-794" would get published to the location "/images/stuff_tcm35-794.png"

The above example highlights two concerns that users of early versions of SDL Tridion had about how it handled binary files. All of the binary files from a specific CMS Publication are stored in a single configurable location (i.e. /images or /files, but it could not deploy binaries to multiple locations), and the filenames of the files were not very user friendly.

SDL Tridion R5.3 introduced a solution to the problem by introducing a new AddBinary() method along with the Modular Templating Framework. This promised to solve all of our problems by introducing a number of additional parameters, the most significant of which was the ability to add the binary to a specific structure group.

E.g. With R5.3, it is possible to add the binary to a special PNG Structure Group and publish the file to the location "/files/png/stuff.png"

This seemed to meet all of the user requirements I had heard over the last several years, but it has introduced a new problem, which many people have run into in the last couple of years. If you have two multimedia components both named "stuff.png" stored in different CMS folders, but you need to use them both in the same Component Presentation (or even in different CPs if you use the default templates) , you will receive the following error when the Broker tries to deploy the files to your web server:

"A processing error occurred processing a transport package. Attempting to deploy a binary [Binary id=tcm:35-795-16 variantId= sg= path=/Images/stuff.png] to a location where a different binary is already stored Existing binary: tcd:pub[35]/binarymeta[794]"

This is kind of expected, as clearly there is a unique naming conflict in this situation. However this situation seems to occur more often than one might think (even using the Default Template Building Blocks that come with the product). Try it for yourself; create two multimedia components based on the same file (i.e. with the same filename). Then create a component which links to them both in an RTF field, and try publishing it using a simple Compound Template as follows:

SDL Tridion Template Builder with multiple images with the same name - Click for larger version

Notice that the Sample Dreamweaver Component Design places two copies of "stuff.png" into the package. The Default Finish Actions (which contains the Publish Binaries In Package template) is then responsible for actually publishing the items in the package, and then the Link Resolver template then modifies the Output item, and update all the URLs of the files in the HTML.

SDL Tridion Template Builder with Default Finish Actions - Click for larger version

I set out to find out exactly what the Publish Binaries In Package template was doing, so I downloaded the sample code from the SDL Tridion Forum at: https://forum.tridion.com/topic.asp?TOPIC_ID=4653. In the PublishBinariesInPackage class, there is a method called ConstructFileName(), which makes use of a number of properties that do not show up when you inspect the package of the with the Template Builder. These are all documented as Public Fields of the Item class in the Templating Implementation Manual (TOM.NET). 

ConstructFilnames() method, screen shot from SDL Tridion Sample Building Blocks - Click for larger version

The key properties here are the Item.ItemPropertyFileName, Item.ItemPropertyFileNamePrefix, Item.ItemPropertyFileNameSuffix and Item.ItemPropertyFileNameExtension. As far as I can tell, the Dreamweaver mediator only utilizes the Item.ItemPropertyFileName property (I am not aware of the source code for the mediator being publicly available, so I can’t be sure of this).

Having spoken with several of the Customer Support and R&D team members, it seems that this is by design, and there is an assumption that developers will ensure the uniqueness of the filenames. This is fine if you write all your own code to publish binaries, but if you want to take advantage of the pre-built building blocks it doesn’t always work.

C# TBB to ensure unique filenames - Click for larger version

To get around this problem, I created a small C# TBB (but could be in an assembly) which can be added to the Default Finish Actions (or directly to a Compound Template) to add a suffix the filenames to all of the binaries in the package (i.e. The file stuff.png becomes stuff35-794.png when it is published by the  Publish Binaries In Package template).

Using the unique filenames C# TBB in SDL Tridion Template Builder - Click for larger version

The result is that we no longer see the "Attempting to deploy a binary to a location where a different binary is already stored" error message popping up in the publishing queue.

Please let me know if you have other/better ways to solve the problem. Until then, I will be including this C# fragment in my Default Finish Actions compound template building block for the foreseeable future.