A very simple media upload via URL

The media upload functionality in Sitecore only handles direct file upload while you sometimes would like to add a media item from the Internet. There are for example Digital Asset Management (DAM) systems that use URL cut and pasting as a means of integration.

The drawbacks of this method of integration is that the web site will depend on the media being available from the DAM system which it may not always be. If for example the DAM is down a single point of failure is introduced in the web site. If the editors remove an image from the DAM system they will have no way of knowing that an image actually is used in a web site. I personally do not think that URL cutting and pasting is a good way of integrating a DAM system, but sometimes you have to deal with the systems already out there.

So instead of yammering about integrations lets make it work. In my opinion if the media can be handled by Sitecore as any other media, it is a good thing. No new single points of failure are introduced and all the caching functionality in Sitecore will be in use. So lets just import the media and put it in the media library.

The first step is to create a new command that we can use to add the media. Just create a class and inherit Sitecore.Shell.Framework.Commands.Command and override the method “Execute”. We need to collect the necessary parameters in that function and start the actual work.

public override void Execute(CommandContext context)
        {
            Assert.ArgumentNotNull((object)context, "context");
            if (context.Items.Length != 1)
                return;
            Item obj = context.Items[0];
            NameValueCollection parameters = new NameValueCollection();
            parameters["id"] = StringUtil.GetString(new string[2]
                                  {
                                    context.Parameters["id"],
                                    obj.ID.ToString()
                                  });
            parameters["language"] = obj.Language.ToString();
            parameters["version"] = obj.Version.ToString();
            Context.ClientPage.Start((object)this, "Run", parameters);
        }

The Execute method does as you can see start a client page with the method Run. So lets create that as well.

protected void Run(ClientPipelineArgs args)
        {
            Assert.ArgumentNotNull((object)args, "args");
            string itemId = args.Parameters["id"];
            string languageName = args.Parameters["language"];
            string version = args.Parameters["version"];
            Item mediaFolderItem = Client.ContentDatabase.Items[itemId, Language.Parse(languageName), Sitecore.Data.Version.Parse(version)];
            if (mediaFolderItem == null)
            {
                SheerResponse.Alert("Item not found.", new string[0]);
            }
            else
            {
                if (args.IsPostBack)
                {
                    Context.ClientPage.SendMessage(this, string.Format("item:refreshchildren(id={0})", mediaFolderItem.ID));
                }
                else
                {
                    {
                        UrlString urlString = new UrlString("/PathToMyCode/UrlUploadMedia.aspx");
                        mediaFolderItem.Uri.AddToUrlString(urlString);
                        SheerResponse.ShowModalDialog(urlString.ToString(), "450", "160", string.Empty, true);
                    }
                    args.WaitForPostBack();
                }
            }
        }

So the Run method will open a modal dialog containing a normal aspx-file. Let us have a look at that file. AddMedia is an OnClick event for a button in the aspx. The Controls that you need on the aspx is two textboxes (tbUrl and tbName) and a literal (message). The AddMedia method will use the Url in tbUrl to download media and give the item the name provided in tbName. If there is no text in tbName it will try to find a name from the URL. When it is done it will simply close the dialog. The Run method above will handle the refreshing of the content tree when the window is closed.

protected void AddMedia(object sender, EventArgs e)
        {
            try
            {
                var queryString = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query);
                var db = Database.GetDatabase(queryString["db"]);
                var parentFolder = db.GetItem(new ID(queryString["id"]));
                var langName = queryString["la"];
                var language = parentFolder.Languages.FirstOrDefault(lang => lang.Name.ToLower() == langName);

                var stream = DownloadFile();
                var fileName = GetFileName();

                var mc = new MediaCreator();
                var mediaCreatorOptions = new MediaCreatorOptions
                    {
                        Database = db,
                        Language = language,
                        Destination = string.Format("{0}/{1}", parentFolder.Paths.ContentPath, fileName),
                        FileBased = false,
                        IncludeExtensionInItemName = false,
                        KeepExisting = false,
                        Versioned = false
                    };
                mc.CreateFromStream(stream, tbUrl.Text, mediaCreatorOptions);

                ClientScript.RegisterStartupScript(this.GetType(), "closeWindow", "window.close();", true);
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message, ex, this);
                message.Text = "Media upload failed";
            }
        }

        private object GetFileName()
        {
            var fileName = FindFileName(tbUrl.Text);
            if (!string.IsNullOrEmpty(tbName.Text))
                fileName = tbName.Text;
            return fileName;
        }

        private Stream DownloadFile()
        {
            WebClient wc = new WebClient();
            var data = wc.DownloadData(tbUrl.Text);
            Stream stream = new MemoryStream(data);
            return stream;
        }

        private object FindFileName(string text)
        {
            var name = text.Substring(text.LastIndexOf('/'));
            name = name.Substring(0, name.LastIndexOf('.'));
            return name;
        }

Add your command to commands.config.

<command name="media:urlupload" type="MediaUpload.Infrastructure.UrlUpload,MediaUpload" />

Find the upload file item (/sitecore/templates/Branches/System/Media/Upload File) and duplicate it  to create an Upload Url Item. Modify the name and the Command.

UploadUrl

Finally add the Upload Url item to the insert options of the media folder’s standard values.

InsertOptions

Now you can right click a media folder and add a media via URL. If you want it to work from the page editor a new button that calls the same command can be added to InsertImage.xml for the rich text editor.

 

Leave a Reply

Your email address will not be published. Required fields are marked *