【问题标题】:adding header to http response in an action inside a controller in asp.net/mvc在 asp.net/mvc 的控制器内的操作中将标头添加到 http 响应
【发布时间】:2013-04-12 06:12:13
【问题描述】:

我正在使用filestream.write 将数据从服务器流式传输到客户端以供下载。在这种情况下,我可以下载该文件,但它在我的浏览器中没有显示为下载。 “另存为”的弹出窗口都不会出现,“下载栏”也不会出现在“下载”部分。环顾四周,我想我需要在响应标头中包含“某物”,以告诉浏览器此响应有附件。我也想设置cookie。为此,我正在这样做:

        [HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment;filename=" & name)]
    public ActionResult Download(string name)
    {
          // some more code to get data in inputstream.

          using (FileStream fs = System.IO.File.OpenWrite(TargetFile))
            {
                byte[] buffer = new byte[SegmentSize];
                int bytesRead;
                while ((bytesRead = inputStream.Read(buffer, 0, SegmentSize)) > 0)
                {
                    fs.WriteAsync(buffer, 0, bytesRead);
                }
            }
        }
        return RedirectToAction("Index");
    }

我收到错误消息:“System.web.httpcontext.current 是一个属性,被用作一种类型。”

我是否在正确的位置更新标题?有没有其他方法可以做到这一点?

【问题讨论】:

    标签: c# asp.net-mvc response httpcontext


    【解决方案1】:
    public FileResult DownloadDocument(string id)
            {
                if (!string.IsNullOrEmpty(id))
                {
                    try
                    {
                        var fileId = Guid.Parse(id);
    
                    var myFile = AppModel.MyFiles.SingleOrDefault(x => x.Id == fileId);
    
                    if (myFile != null)
                    {
                        byte[] fileBytes = myFile.FileData;
                        return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, myFile.FileName);
                    }
                }
                catch
                {
                }
            }
    
            return null;
        }
    

    【讨论】:

      【解决方案2】:

      过去,我建立了一个白名单,以允许某些域对我的网站进行 iframe。还记得 Google 用于 iframe 网站的图片缓存。

      static HashSet<string> frameWhiteList = new HashSet<string> { "www.domain.com",
                                                          "mysub.domain.tld",
                                                          "partner.domain.tld" };
      
          protected void EnforceFrameSecurity()
          {
              var framer = Request.UrlReferrer;
              string frameOptionsValue = "SAMEORIGIN";
      
              if (framer != null)
              {
                  if (frameWhiteList.Contains(framer.Host))
                  {
                      frameOptionsValue = string.Format("ALLOW-FROM {0}", framer.Host);
                  }
      
              }
      
              if (string.IsNullOrEmpty(HttpContext.Current.Response.Headers["X-FRAME-OPTIONS"]))
              {
                  HttpContext.Current.Response.AppendHeader("X-FRAME-OPTIONS", frameOptionsValue);
              }
          }
      

      【讨论】:

        【解决方案3】:

        是的,你做错了试试这个,你应该在你的动作中添加标题,而不是作为属性标题添加到你的方法中。

        HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment;filename=" & name)
        

        Request.RequestContext.HttpContext.Response.AddHeader("Content-Disposition", "Attachment;filename=" & name)
        

        更新 据我了解,您正在对您的控制器/动作进行 ajax 调用,这将无法通过直接调用动作来下载文件。您可以通过这种方式实现它。

        public void Download(string name)
                {
        //your logic. Sample code follows. You need to write your stream to the response.
        
                    var filestream = System.IO.File.ReadAllBytes(@"path/sourcefilename.pdf");
                    var stream = new MemoryStream(filestream);
                    stream.WriteTo(Response.OutputStream);
                    Response.AddHeader("Content-Disposition", "Attachment;filename=targetFileName.pdf");
                    Response.ContentType = "application/pdf";
                }
        

            public FileStreamResult Download(string name)
            {
                var filestream = System.IO.File.ReadAllBytes(@"path/sourcefilename.pdf");
                var stream = new MemoryStream(filestream);
        
        
                return new FileStreamResult(stream, "application/pdf")
                {
                    FileDownloadName = "targetfilename.pdf"
                };
            }
        

        在你的 JS 按钮中点击你可以做类似的事情。

         $('#btnDownload').click(function () {
                    window.location.href = "controller/download?name=yourargument";
            });
        

        【讨论】:

        • 我试过这样做。但它仍然既不显示“另存为”对话框,也不显示浏览器下载部分的下载进度条。
        • 这对我有用,我看到在我的测试用例中下载了视图 html。对您来说,这可能是因为您正在重定向到操作。我还没有尝试过这种情况。只需尝试将此标题放在索引下即可。
        • 我会详细一点。我在“索引”页面,然后单击下载,然后通过 JavaScript 调用下载操作。上面的代码是用下载动作编写的。在将文件流式传输给用户之后,我重定向到索引页面。我很困惑什么时候应该告诉浏览器有下载。我的意思是我正在使用 FileStream.WriteSync 发送内容,所以我想我需要在发送文件之前告诉浏览器有附件,因此它会弹出“另存为”对话框。我认为我对这里的工作流程感到困惑,因此不知道应该在何时何地进行更改。
        • 好的,明白了。所以你想开始下载,不管你想重定向到你的新页面。
        • 您说您是通过 javascript 引导操作,您使用的是 xhr 请求、ajax 请求还是 location.href?
        【解决方案4】:

        变化:

        return RedirectToAction("Index");
        

        到:

        return File(fs, "your/content-type", "filename");
        

        并将 return 语句移动到您的 using 语句中。

        【讨论】:

          【解决方案5】:

          请看here

          以下内容来自参考网站。

          public FileStreamResult StreamFileFromDisk()
          {
              string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";
              string fileName = "test.txt";
              return File(new FileStream(path + fileName, FileMode.Open), "text/plain", fileName);
          }
          

          编辑 1:

          从我们的优秀 SO 中添加一些您可能更感兴趣的内容。 您可以查看完整的详细信息here

          public ActionResult Download()
          {
              var document = ...
              var cd = new System.Net.Mime.ContentDisposition
              {
                  // for example foo.bak
                  FileName = document.FileName, 
          
                  // always prompt the user for downloading, set to true if you want 
                  // the browser to try to show the file inline
                  Inline = false, 
              };
              Response.AppendHeader("Content-Disposition", cd.ToString());
              return File(document.Data, document.ContentType);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-06-12
            • 1970-01-01
            • 2021-02-17
            • 2019-02-06
            • 1970-01-01
            • 1970-01-01
            • 2012-08-01
            相关资源
            最近更新 更多