為什么瀏覽器中有些圖片、PDF等文件點(diǎn)擊后有些是預(yù)覽,有些是下載,
出現(xiàn)圖片、PDF不能預(yù)覽的情況,主要是通過(guò)代碼輸出文件流的形式,非IIS、Nginx下直接訪問(wèn)資源的方式產(chǎn)生的
在HTTP中,用于文件下載的常見(jiàn)響應(yīng)頭(response headers)包括:
Content-Disposition:
用于指示瀏覽器應(yīng)該如何處理響應(yīng)體。在文件下載中,通常設(shè)置為 attachment; filename="filename.jpg",其中 filename.jpg 是要下載的文件名。
Content-Type:
指示響應(yīng)體的MIME類(lèi)型,例如 image/jpeg 或 application/pdf。
Content-Length:
響應(yīng)體的長(zhǎng)度(以字節(jié)為單位)。
Cache-Control:
控制緩存的行為,通??梢栽O(shè)置為 no-cache 禁止緩存。
Expires:
指定響應(yīng)的過(guò)期時(shí)間,與 Cache-Control 一起使用來(lái)控制緩存。
Pragma:
舊版本的HTTP使用的頭部,現(xiàn)在基本不再使用,可以設(shè)置為 no-cache。
Content-Disposition
Content-Disposition 是一個(gè)HTTP響應(yīng)頭部,指示瀏覽器如何處理接收到的響應(yīng)體內(nèi)容。它可以讓服務(wù)器指定一個(gè)文件名,或者指示瀏覽器直接顯示內(nèi)容(inline)或者將內(nèi)容作為附件下載(attachment)。
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="example.txt"
文件下載
通常情況下,服務(wù)器會(huì)使用 Content-Disposition: attachment
頭部來(lái)強(qiáng)制瀏覽器下載文件,而不是嘗試在瀏覽器中打開(kāi)它。例如:
Content-Disposition: attachment; filename="example.pdf"
Content-Type: application/pdf
內(nèi)聯(lián)顯示
服務(wù)器可能希望瀏覽器直接在頁(yè)面內(nèi)顯示內(nèi)容,而不是下載它。例如,對(duì)于一些直接展示的文件類(lèi)型(如圖片、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,圖片這樣的就可以在瀏覽器內(nèi)直接預(yù)覽了
headers.add("filename", URLEncoder.encode(file.getName(), "UTF-8"));
headers.add("Access-Control-Expose-Headers", "filename"); //這個(gè)要加,否則Vue 在 res.headers['filename'] 時(shí)取不到值
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";
//根據(jù)服務(wù)器文件的擴(kuò)展名決定使用什么樣的方式輸出
switch (foundFileInfo.Extension)
{
case ".xml":
mediaType = "text/xml";
contentDisposition = "inline; //瀏覽器預(yù)覽
break;
case ".pdf":
mediaType = "application/pdf";
contentDisposition = "inline; //瀏覽器預(yù)覽
break;
case ".jpg":
case ".jpeg":
mediaType = "image/jpg";
contentDisposition = "inline; //瀏覽器預(yù)覽
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 校驗(yàn)碼
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;
}
常見(jiàn)的媒體類(lèi)型
text/plain:純文本。
text/html:HTML 文檔。
application/json:JSON 數(shù)據(jù)。
application/xml:XML 數(shù)據(jù)。
image/jpeg、image/png:JPEG 或 PNG 圖像。
multipart/form-data:用于文件上傳的表單數(shù)據(jù)。
文件上傳
在使用表單上傳文件時(shí),通常會(huì)使用 multipart/form-data 媒體類(lèi)型,并指定邊界字符串。例如:
Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6