zoukankan      html  css  js  c++  java
  • .Net 如何修改 HttpHeaders 中的 Content-Disposition

    最近在看一些.Net5的内容,于是就想将之前Spring写的一个项目迁移到.Net上来看看。

    不得不说.Net这几年发展的确实挺好的,超快的启动速度,极佳的性能让它一点不比Java差,但确实在国内生态有一些问题,一些问题的答案确实不那么好找,就比如我先在遇到的这个问题。

    问题一:如何修改Content-Disposition属性

    一个简单下载查看文件的功能,我可以选择下载还是查看本地的文件,代码非常简单,就像这样:

            /// <summary>
            /// 加载文件
            /// </summary>
            /// <param name="path">文件路径</param>
            /// <param name="type">加载模式</param>
            /// <returns>文件</returns>
            [Route("file")]
            [HttpGet]
            public async Task<IActionResult> DownloadFile(string path, string type)
            {
                if (string.IsNullOrEmpty(path))
                {
                    return Content("404 for not found!");
                }
    
                try
                {
                    var filePath = PathFilterUtil.PathFilter(RUN_PATH, path);
    
                    var memoryStream = new MemoryStream();
                    using (var stream = new FileStream(filePath, FileMode.Open))
                    {
                        await stream.CopyToAsync(memoryStream);
                    }
                    
                    memoryStream.Position = 0;
                    // 获取文件的ContentType
                    string fileExt = Path.GetExtension(path);
                    var provider = new FileExtensionContentTypeProvider();
                    var memi = provider.Mappings[fileExt];
                    if (type == "inline")
                    {
                        Response.Headers.Add("Content-Disposition", $"inline; filename={Path.GetFileName(filePath)}");
                        return File(memoryStream, memi, Path.GetFileName(filePath));
                    }
                    return File(memoryStream, memi, Path.GetFileName(filePath));
                }
                catch (DirectoryNotFoundException e)
                {
                    _logger.LogError($"文件:{path},没有找到!
    {e.Message}");
                    return Content("404 for not found!");
                }
                
            }
    

    我需要修改 HttpHeadersContent-Disposition 属性,将默认的 attachment 根据需要变成 inline,但是我按照上面的说法,怎么都改不了它的 Content-Disposition属性,不论则样它永远返回的是Content-Disposition: attachment; filename=appsettings.json; filename*=UTF-8''appsettings.json这样。

    通过查找资料

    期间我尝试了将Response.Headers.Add()方法变成Response.Headers.Append(),我甚至在百度看见了 Response.AddHeader()这种早已过时的方法,真滴离谱。

    后来我终于在stackoverflow上找到了答案,不得不说还是stackoverflow强。

                    if (type == "inline")
                    {
                        
                        Response.Headers.Add("Content-Disposition", $"inline; filename={Path.GetFileName(filePath)}");
                        return File(memoryStream, memi);
                    }
    

    方法很简单,删除return File(memoryStream, memi, Path.GetFileName(filePath)); 后面 Path.GetFileName(filePath)这个获取文件名的方法就好。

    问题二:中文文件下载报InvalidOperationException: Invalid non-ASCII or control character in header:

    这个不多说了,就是编码的问题,在Response.Headers.Add("Content-Disposition", $"inline; filename={Path.GetFileName(filePath)}");写入文件名时,不能直接写入文件,需要进行转码,这个转码的方法我又查了好久,最后还是在stackoverflow找到的,这两个问题真的是体现出了.Net在国内发展不咋地。

    这要是Java,随便一查答案就出来了。

    具体解决就是使用System.Net.WebUtility.UrlEncode()对文件名进行重新编码。像这样

                    if (type == "inline")
                    {
                        
                        Response.Headers.Add("Content-Disposition", $"inline; filename={System.Net.WebUtility.UrlEncode(Path.GetFileName(filePath))}");
                        return File(memoryStream, memi);
                    }
    

    完整代码

            /// <summary>
            /// 加载文件
            /// </summary>
            /// <param name="path">文件路径</param>
            /// <param name="type">加载模式</param>
            /// <returns>文件</returns>
            [Route("file")]
            [HttpGet]
            public async Task<IActionResult> DownloadFile(string path, string type)
            {
                if (string.IsNullOrEmpty(path))
                {
                    return Content("404 for not found!");
                }
    
                try
                {
                    var filePath = PathFilterUtil.PathFilter(RUN_PATH, path);
    
                    var memoryStream = new MemoryStream();
                    using (var stream = new FileStream(filePath, FileMode.Open))
                    {
                        await stream.CopyToAsync(memoryStream);
                    }
                    
                    memoryStream.Position = 0;
                    // 获取文件的ContentType
                    string fileExt = Path.GetExtension(path);
                    var provider = new FileExtensionContentTypeProvider();
                    var memi = provider.Mappings[fileExt];
                    _logger.LogInformation($"当前请求访问下载文件目录:{filePath}   {Path.GetFileName(filePath)}");
                    if (type == "inline")
                    {
                        
                        Response.Headers.Add("Content-Disposition", $"inline; filename={System.Net.WebUtility.UrlEncode(Path.GetFileName(filePath))}");
                        return File(memoryStream, memi);
                    }
                    return File(memoryStream, memi, Path.GetFileName(filePath));
                }
                catch (DirectoryNotFoundException e)
                {
                    _logger.LogError($"文件:{path},没有找到!
    {e.Message}");
                    return Content("404 for not found!");
                }
                
            }
    

    版权

    本文首发于https://www.buguagaoshu.com/archives/net%E5%A6%82%E4%BD%95%E4%BF%AE%E6%94%B9heepheaders,转载请注明来源

  • 相关阅读:
    百度地图API地理位置和坐标转换
    WebClient 通过get和post请求api
    C#模拟POST提交表单(二)--HttpWebRequest以及HttpWebResponse
    C#模拟POST提交表单(一)--WebClient
    百度外卖接口调试 C#版
    DWZ(JUI) 教程 跨域请求 iframeNavTab
    订餐系统之同步美团商家订单
    订餐系统之同步饿了么商家订单
    外卖订单爬虫(美团,饿了么,百度外卖)
    订餐系统之获取淘宝外卖订单
  • 原文地址:https://www.cnblogs.com/puzhiwei/p/15265005.html
Copyright © 2011-2022 走看看