Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Frederik Vig 29 posts 61 karma points
    Oct 19, 2009 @ 12:17
    Frederik Vig
    0

    Most popular downloads

    Hi!

    I'm trying to create an overview of the 10 most popular downloads from a given place in the Media library. So my question is how does Umbraco handle a request for a file in the media library? Has far as I can tell IIS handles the requests and not ASP.NET..

    I'm not that familiar with Umbraco (working on my first site now), my apologize if this question has been asked before :).

    Thanks!

    Cheers

    Frederik

  • Paul Marden 235 posts 338 karma points MVP c-trib
    Oct 19, 2009 @ 13:08
    Paul Marden
    1

    Frederik -- All Umbraco does is output an url to the media item.  So there's no tracking of downloads of media items from your XSLT.

  • Frederik Vig 29 posts 61 karma points
    Oct 19, 2009 @ 13:16
    Frederik Vig
    0

    Hi Paul!

    Do you know how Umbraco points domename.com/media/somefolder/somefile.ext to the local media/1234/somefile.ext? I presume it uses an Http Module for this, but not sure how it will work since all requests go through IIS and not ASP.NET (no wildcard setup).

    Cheers

    Frederik

  • Niels Hartvig 1951 posts 2391 karma points c-trib
    Oct 19, 2009 @ 13:45
    Niels Hartvig
    0

    It just points to the physical file on the server which is stored at that location. No magic at all :)

  • Nik Wahlberg 639 posts 1237 karma points MVP
    Oct 19, 2009 @ 13:48
    Nik Wahlberg
    1

    The first thing that comes to mind is creating a User Control that serves your files. This UC would have a public property "MediaId" which then grabs the Media Item and and stores stats on the media item in a file or database before returning the media item to the page or download. Should be fairly straight forward to do.

    Let us know if you need some pointers.

    Cheers,
    Nik

  • Dirk De Grave 4541 posts 6021 karma points MVP 3x admin c-trib
    Oct 19, 2009 @ 14:05
    Dirk De Grave
    0

    Great solution for links to media files which you may control yourself (from developer's perspective), but won't work if inserted in rte for example (as an editor problably won't know about this construct). You'd need another solution to handle those (which is possible but requires some coding to change default behaviour when selecting a media item from the 'select media item' dialog in the rte)

     

    Cheers,

    /Dirk

  • Frederik Vig 29 posts 61 karma points
    Oct 19, 2009 @ 14:18
    Frederik Vig
    0

    @Niels ah I see it now.. Got thrown by the fact that in Umbraco UI it displayed a friendly folder name instead of the numbers :).

    @Nik I'm not sure I follow. I was thinking of enabling wildcard mapping and use an Http Handler for all requests and just check there if the request path contains media in it.

    Question: Since I only want to log downloads for a particular sub folder of media I should store this reference in Umbraco. Is there a way to access an Umbraco Property from my handler? If yes what class should I inherit from?

    Thanks again!

    Frederik

  • Frederik Vig 29 posts 61 karma points
    Oct 19, 2009 @ 14:27
    Frederik Vig
    1

    @Nik I think I understand your solution now.. :). And it will actually work for my scenario, since the editor is only pointing to a folder, which I then use to list all the files for download.

    Though I still wonder about the custom handler approach. Would be nice to know for file permissions etc.

  • Frederik Vig 29 posts 61 karma points
    Oct 20, 2009 @ 11:12
    Frederik Vig
    0

    Okay, I've create a Generic handler now which returns the file. But I still need a way of storing the number of downloads. I've looked at the addProperty method but not sure how I programmatically add a new property. Any pointers?

    Cheers

    Frederik

  • Frederik Vig 29 posts 61 karma points
    Oct 20, 2009 @ 12:26
    Frederik Vig
    3

    Wrote to an XML file instead. Would be nice to know though, how to do this by adding a property to the media item.

    For those interested below is the code I used:

    using System;
    using System.IO;
    using System.Web;
    using System.Web.Services;
    using umbraco.cms.businesslogic.media;

    namespace Company.Handlers
    {
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class MediaHandler : IHttpHandler
    {

    public void ProcessRequest(HttpContext context)
    {
    var mediaId = context.Request.QueryString["mediaId"];
    int id;

    int.TryParse(mediaId, out id);

    var media = new Media(id);
    if (media.Id != id)
    {
    return;
    }

    var download = new Download().GetDownload(media.Id) ??
    new Download { MediaId = media.Id, Count = 0, LastModified = DateTime.Now };

    download.Count++;
    download.Save();

    try
    {
    string filePath = context.Server.MapPath(media.getProperty("umbracoFile").Value.ToString());

    var file = new FileInfo(filePath);
    context.Response.Clear();
    context.Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
    context.Response.AddHeader("Content-Length", file.Length.ToString());
    context.Response.ContentType = "application/octet-stream";

    context.Response.WriteFile(filePath);
    context.Response.End();
    }
    catch (Exception)
    {
    return;
    }
    }

    public bool IsReusable
    {
    get
    {
    return true;
    }
    }
    }
    }

    Download.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Xml.Linq;

    namespace Company
    {
    public class Download
    {
    public int MediaId
    {
    get; set;
    }

    public int Count
    {
    get; set;
    }

    public DateTime LastModified
    {
    get; set;
    }

    public List<Download> GetAllDownloads()
    {
    var downloads = from download in XElement.Load(HttpContext.Current.Server.MapPath("~/XML/downloads.xml")).Elements("download")
    select new Download
    {
    MediaId = (int) download.Attribute("mediaid"),
    Count = (int) download.Element("count"),
    LastModified = (DateTime) download.Element("lastmodified")
    };

    return downloads.ToList();
    }

    public void Save()
    {
    var downloads = this.GetAllDownloads();
    var download = downloads.Where(d => d.MediaId == this.MediaId).FirstOrDefault();

    if (download != null)
    {
    downloads.Remove(download);
    }

    downloads.Add(this);

    try
    {
    var xml = new XElement("downloads");
    foreach (var downloadData in downloads)
    {
    xml.Add(new XElement("download",
    new XAttribute("mediaid", downloadData.MediaId),
    new XElement("count", downloadData.Count),
    new XElement("lastmodified", downloadData.LastModified)
    ));
    }

    xml.Save(HttpContext.Current.Server.MapPath("~/XML/downloads.xml"));
    }
    catch (Exception)
    {
    // Logging
    }
    }

    public Download GetDownload(int mediaId)
    {
    return this.GetAllDownloads().Where(d => d.MediaId == mediaId).FirstOrDefault();
    }
    }
    }

    The links use the MediaHandler:

    <a href="/Handlers/Mediahandler.ashx?mediaId=1116">Filename</a>

    Note that I use a Generic Handler which means I don't have to register it in my web.config.

    Downloads.xml - remember to give either the aspnet (on Windows XP) or the Network Service user modify rights.

    <?xml version="1.0" encoding="utf-8"?>
    <downloads>
    <download mediaid="1117">
    <count>1</count>
    <lastmodified>2009-10-20T12:13:43.61011+02:00</lastmodified>
    </download>
    <download mediaid="1116">
    <count>2</count>
    <lastmodified>2009-10-20T12:13:41.7549245+02:00</lastmodified>
    </download>
    </downloads>

    Hope this helps.

  • Nik Wahlberg 639 posts 1237 karma points MVP
    Oct 20, 2009 @ 14:28
    Nik Wahlberg
    0

    Fredrik,

    this looks like a great solution. Thanks for sharing with the rest of the community as I am sure this will come in handy for others as well.

    Cheers,
    Nik

Please Sign in or register to post replies

Write your reply to:

Draft