tags:

views:

25

answers:

2

I have a URL to a file, "http://mydomain.domain.com/files/somefile.mp3".

I also have an Action in my Controller.

I want the action to return the file as an attachment.

I know I can do this:

Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName)
Response.AddHeader("Content-Length", lenOfFile)
Response.ContentType = "application/octet-stream" 

But does that mean that the return type of the Action is void? And then what do I call to tell it to send?

I also tried:

return File(new FileStream(a.AssetPath, FileMode.Open), "application/octet-stream");

when the return type of the Action was FileStreamResult but it did not like the fact that my path was a URL.

A: 

Maybe with one of the sub classes of FileResult -> http://msdn.microsoft.com/en-us/library/system.web.mvc.fileresult.aspx

If non of the built-in work, you can write your own actionresult, with just the code you posted.

ps. random ActionResult example from a quick search

eglasius
+1  A: 

I would suggest writing your own ActionResult, like this:

public class FileUriResult : ActionResult
{
  private string _contentType;
  private string _fileUri;
  private long _fileLength;

  public FileUriResult(string contentType, string fileUri, long fileLength)
  {
    _contentType = contentType;
    _fileUri = fileUri;
    _fileLength = fileLength;
  }

  public override void ExecuteResult(ControllerContext context)
  {
    if (context == null)
    {
      throw new ArgumentNullException("context");
    }
    HttpResponseBase response = context.HttpContext.Response;
    response.ContentType = _contentType;
    response.AddHeader("Content-Disposition", "attachment; filename=" + _fileUri);
    response.AddHeader("Content-Length", _fileLength.ToString(); 
  }
}

Then just use it in your action method:

return new FileUriResult("application/octet-stream", a.AssetPath, lenOfFile);                    
tpeczek
How can I get lenOfFile? Something like this maybe? http://stackoverflow.com/questions/122853/c-get-http-file-size ... and if the length of the file is unavailable can anything be done?
shogun
Content-Length header is not obligatory, please read the following links: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13, http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
tpeczek
I am getting an error with this code, instead of downloading the file that exists at the path it is sending me 0kb files that simply have the same name as the real file, sample path would be like "http://domain.com/folder/file.mp3"... any idea?
shogun
Well yes. I trusted in what you write and haven't tested it. But the headers themself will not make any result, you have to put file content into response. Stupid of me...
tpeczek
After some thinking, I need to ask you few question. Do you really have to send file from other server than your applicaton is using (because if you are sending local file, you can use local path with one of standard results). If you have to send file from other server, than why can't you just make a direct link in html? If none of the above is an option, I will prepare you a code which downloads a file from remote server and sends it to client, but thats not efficient solution.
tpeczek
Yeah you are right that does seem slower, the whole point of having the files on the other server is that it is a CDN host so it's suppose to be really fast globally, if I am downloading it to my web server and handing it back it defeats the whole purpose, I need some way though to tell the file, no matter what the type is, to download as a file attachment and not play it in the browser, I can't think of any other way than this but you're right, it defeats the purpose of itself.
shogun
If despite this, you want me to edit the response and make it working code (with download to the server), let me know.
tpeczek