I had a requirement on a recent project to download a .CSV from within Sitecore User Manager. Basically, it was to download all users within a particular domain. The ‘download’ bit proved tricky, though.
To add a new button to Sitecore’s ribbons, you need to:
- Add entries in Core (in my case /sitecore/content/Applications/Security/User Manager/Ribbon/Home/ ) for the ribbon section and button. Note that you have to specify a command to be run.
- Add a patch file that defines that command, using the class and assembly names.
- Write a class to implement the command call.
All that’s fine – but then, in a postback to a Sitecore window, how do you force a file to be downloaded? My usual approach – using the HTTPResponse class for the current control – doesn’t work.
Well, I found one suggestion by Alan Coates – “open another window“- and later another by Ishraq Fataftah of “use an iframe” – which would both probably work, but feel … inelegant. I really don’t like iFrames, and new Windows aren’t ideal. I noticed that the SheerResponse class has a Download() method… but it needs a file path. On Disk. so I’d have to write my file to disk.
Well, isn’t that what the Temp folder is for?
Thus, my code became:
// Flush csvStream into MemoryStream 'mem'
csvStream.Flush();
// Generate a file path in Temp
string filePath = string.Format("/temp/File {0}.csv", DateTime.Now.ToString("yyyy-MM-dd HHmmssf"));
// Write to disc
byte[] memArr = mem.ToArray();
FileUtil.WriteToFile(filePath, ref memArr );
// Download from disc
SheerResponse.Download(filePath);
This works nicely – the file gets created in Temp, and then downloads to the client thanks to the SheerResponse.Download() call. No iFrames, no new windows.
Oh, bonus note – CSVHelper is brilliant for actually generating CSV files. I just add the Nuget, and away we go.