Download file within Content Editor

In your practice, you may need to be able to generate and download a file while in the Content Editor. I’ll show you how to do this in such example: suppose you need to be able to download a text file that contains the id and the name of the item selected in the Content Tree.

The element of the interface that initiates the file download is a button in the ribbon. So first you need to create a custom button. There are a lot of articles on the Internet about how to do this, e.g. how-to-add-a-custom-sitecore-button-to-the-editor-ribbon.

Further implement TxtReport command class

namespace Report.Components.Commands.Report
{
    using Sitecore.Data;
    using Sitecore.Diagnostics;
    using Sitecore.Shell.Framework.Commands;
    using Sitecore.Text;
    using Sitecore.Web;
    using Sitecore.Web.UI.Sheer;

    public class TxtReport : Command
    {
        public override void Execute(CommandContext context)
        {
            var item = context.Items[0];
            Assert.IsNotNull(item, "item");

            OpenNewWindow(item.ID);
        }

        private void OpenNewWindow(ID id)
        {
            const string downloadReportPage = "/Components/Commands/Report/DownloadReport.aspx";
            var urlWithParameters = WebUtil.AddQueryString(downloadReportPage, "id", id.ToString());
            var url = new UrlString(urlWithParameters);
            SheerResponse.Eval($"window.open('{url}');");
        }
    }
}

To make TxtReport works in proper way you should creare DownloadReport web form. The path
is “/Components/Commands/Report/DownloadReport.aspx” (used in OpenNewWindow method of TxtReport class). In your case most propably it’ll be different.

This line of code opens new tab

SheerResponse.Eval($"window.open('{url}');");

The rest of logic is in code behind of DownloadReport web form.

namespace Report.Components.Commands.Report
{
    using Sitecore.Configuration;
    using Sitecore.Data.Items;
    using Sitecore.Diagnostics;
    using System;
    using System.IO;
    using System.Text;
    using System.Web;

    public partial class DownloadReport : System.Web.UI.Page
    {
        private string Id => HttpContext.Current.Server.UrlDecode(Request.QueryString["id"]) ?? string.Empty;

        protected void Page_Load(object sender, EventArgs e)
        {
            Assert.ArgumentNotNull(Response, "response");
            Assert.ArgumentNotNullOrEmpty(Id, "Id");

            var item = Factory.GetDatabase("master").GetItem(this.Id);

            var textOfReport = this.PrepareTextOfReport(item);
            var stream = this.ToStream(textOfReport);

            Response.Clear();
            Response.ContentType = "text/plain";
            Response.AddHeader("Content-Disposition", "attachment; filename=report.txt");
            Response.Charset = "UTF-8";
            Response.BinaryWrite(this.ReadFully(stream));
            Response.End();
        }

        private string PrepareTextOfReport(Item item)
        {
            var sb = new StringBuilder();
            sb.AppendFormat("Item Id: {0}", item.ID);
            sb.Append(Environment.NewLine);
            sb.AppendFormat("Item name: {0}", item.Name);

            return sb.ToString();
        }

        public Stream ToStream(string s)
        {
            var stream = new MemoryStream();
            var writer = new StreamWriter(stream);

            writer.Write(s);
            writer.Flush();

            stream.Position = 0;

            return stream;
        }

        private byte[] ReadFully(Stream input)
        {
            using (var ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }
        }
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s