开发者

How to add a file attachment to the Response when the file path is a URI in MVC.NET Actions?

开发者 https://www.devze.com 2023-01-15 10:56 出处:网络
I have a URL to a file, \"http://mydomain.domain.com/files/somefile.mp3\". I also have an Action in my Controller.

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 attachm开发者_Go百科ent.

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.


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


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);                    


What you needed was to use a WebRequest to get the file and then use FileResult to give it back to the client.

public static FileResult FileWebRequest(this Controller controller, Uri uri, 
  string contentType) 
{
  return controller.FileWebResult(uri, contentType, null);
}

public static FileResult FileWebResult(this Controller controller, Uri uri, 
  string contentType, string fileDownloadName) 
{
  WebRequest request = WebRequest.Create(uri);
  using (WebResponse response = request.GetResponse()) 
  {
    byte[] buffer = new byte[response.ContentLength];
    using (Stream responseStream = response.GetResponseStream())
    using (MemoryStream memStream = new MemoryStream()) 
    {
      int bytesRead;
      int totalBytesRead = 0;
      while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) 
      {
        memStream.Write(buffer, totalBytesRead, bytesRead);
      }
      FileResult result = new FileContentResult(memStream.ToArray(), contentType);
      if (fileDownloadName != null) {
        result.FileDownloadName = fileDownloadName;
      }
      return result;
    }
  }
}

Then to use you just call like this from your controller:

return this.FileWebResult(new Uri("http://mydomain.domain.com/files/somefile.mp3"), 
  "application/octet-stream", fileName);
0

精彩评论

暂无评论...
验证码 换一张
取 消