目录
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载,
出现图片、PDF不能预览的情况,主要是通过代码输出文件流的形式,非IIS、Nginx下直接访问资源的方式产生的
在HTTP中,用于文件下载的常见响应头(response headers)包括:
Content-Disposition:
用于指示浏览器应该如何处理响应体。在文件下载中,通常设置为 attachment; filename="filename.jpg",其中 filename.jpg 是要下载的文件名。
Content-Type:
指示响应体的MIME类型,例如 image/jpeg 或 application/pdf。
Content-Length:
响应体的长度(以字节为单位)。
Cache-Control:
控制缓存的行为,通常可以设置为 no-cache 禁止缓存。
Expires:
指定响应的过期时间,与 Cache-Control 一起使用来控制缓存。
Pragma:
旧版本的HTTP使用的头部,现在基本不再使用,可以设置为 no-cache。
Content-Disposition
Content-Disposition 是一个HTTP响应头部,指示浏览器如何处理接收到的响应体内容。它可以让服务器指定一个文件名,或者指示浏览器直接显示内容(inline)或者将内容作为附件下载(attachment)。
- inline:浏览器尝试在页面内显示响应内容,通常用于非下载内容,如 PDF 在线预览。
- attachment:浏览器强制下载响应内容,并提示用户保存到本地。
Content-Disposition: inline Content-Disposition: attachment Content-Disposition: attachment; filename="example.txt"
文件下载
通常情况下,服务器会使用 Content-Disposition: attachment
头部来强制浏览器下载文件,而不是尝试在浏览器中打开它。例如:
Content-Disposition: attachment; filename="example.pdf" Content-Type: application/pdf
内联显示
服务器可能希望浏览器直接在页面内显示内容,而不是下载它。例如,对于一些直接展示的文件类型(如图片、PDF等),可以使用
Content-Disposition: attachment; filename="example.pdf" Content-Type: application/pdf
代码示例
SpringBoot 接口输出文件流:
https://www.cnblogs.com/vipsoft/p/16662762.html
https://www.cnblogs.com/vipsoft/p/16318030.html
//省去判断,参考下面的C# headers.add("Content-Disposition", "attachment; filename=" + URLEncoder.encode(file.getName(), "UTF-8")); //如果是 attachment 换成 inline ,像PDF,图片这样的就可以在浏览器内直接预览了 headers.add("filename", URLEncoder.encode(file.getName(), "UTF-8")); headers.add("Access-Control-Expose-Headers", "filename"); //这个要加,否则Vue 在 res.headers['filename'] 时取不到值
C# 伪代码
[HttpGet] [Route("reportFile")] public HttpResponseMessage ReportFile([FromBody] Order param) { HttpResponseMessage result = null; try { string projectId = HttpContext.Current.Request.QueryString["ProjectId"]; FileInfo foundFileInfo = new FileInfo(filePath); if(!foundFileInfo.Exists) { return new HttpResponseMessage(HttpStatusCode.NotFound); } string mediaType = "application/pdf"; string contentDisposition = "attachment"; //根据服务器文件的扩展名决定使用什么样的方式输出 switch (foundFileInfo.Extension) { case ".xml": mediaType = "text/xml"; contentDisposition = "inline; //浏览器预览 break; case ".pdf": mediaType = "application/pdf"; contentDisposition = "inline; //浏览器预览 break; case ".jpg": case ".jpeg": mediaType = "image/jpg"; contentDisposition = "inline; //浏览器预览 break; case ".png": mediaType = "image/png"; contentDisposition = "inline; //浏览器下载 break; ... default: mediaType = "application/octet-stream"; contentDisposition = "attachment"; //浏览器下载 break; } FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); result = new HttpResponseMessage(HttpStatusCode.OK); result.Content = new StreamContent(fs); //result.Content.Headers.Add("MD5File", Md5Helper.GetMD5HashFromFile(filePath)); //可以在Header里加上 md5 校验码 result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(mediaType); result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(contentDisposition); result.Content.Headers.ContentDisposition.FileName = foundFileInfo.Name; } catch (Exception ex) { logger.Error(ex, ex.Message); result = new HttpResponseMessage(HttpStatusCode.BadRequest); } return result; }
常见的媒体类型
- text/plain:纯文本。
- text/html:HTML 文档。
- application/json:JSON 数据。
- application/xml:XML 数据。
- image/jpeg、image/png:JPEG 或 PNG 图像。
- multipart/form-data:用于文件上传的表单数据。
文件上传
在使用表单上传文件时,通常会使用 multipart/form-data 媒体类型,并指定边界字符串。例如:
Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6