java介面返回圖片連結或pdf連結如何設定線上預覽還是下載

2023-06-15 06:00:52

之前文章說到了如何通過將檔案轉成圖片或者pdf來實現線上預覽,一般來說線上預覽圖片或者pdf都是儲存在圖片伺服器上的,在通過介面呼叫把檔案返回給前端,但是把檔案返回給前端效果一般是有兩種:線上預覽和下載。那這兩種效果分別又該怎麼實現呢?我們今天就來說這兩種效果的實現。

下面是之前轉成圖片、pdf實現線預覽,有興趣的小夥伴可以看看。

檔案線上預覽(一)通過將txt、word、pdf轉成圖片實現線上預覽功能

檔案線上預覽(四)將word、txt、ppt、excel、圖片轉成pdf來實現線上預覽

​ 其實介面實現線上預覽和下載很簡單,只需要通過設定content-type和Content-Disposition這兩個http的響應檔頭就可以實現:

​ Content-Disposition是HTTP協定中的一個頭部欄位,用於指示如何顯示附加的檔案。它是MIME協定的擴充套件,最初在MIME標準中定義。Content-Disposition頭部欄位可以控制使用者請求所得的內容存為一個檔案的時候提供一個預設的檔名,檔案直接在瀏覽器上顯示或者在存取時彈出檔案下載對話方塊。

在常規的 HTTP 應答中,Content-Disposition 響應檔頭指示回覆的內容該以何種形式展示,是以內聯的形式(即網頁或者頁面的一部分),還是以附件的形式下載並儲存到本地。

multipart/form-data 型別的應答訊息體中,Content-Disposition 通用檔頭可以被用在 multipart 訊息體的子部分中,用來給出其對應欄位的相關資訊。各個子部分由在 Content-Type中定義的邊界(boundary)分隔。用在訊息體自身則無實際意義。

作為訊息主體的檔頭

在 HTTP 場景中,第一個引數有以下兩種

  • inline:表示回覆中的訊息體會以頁面的一部分或者整個頁面的形式展示
  • attchment:以附件形式被下載到本地;大多數瀏覽器會呈現一個「儲存為」的對話方塊,將 filename 的值預填為下載後的檔名,假如它存在的話

第二個引數 filename 代表被傳輸的檔名稱(可選)

Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"

備註: 在同源 URL情況下,Chrome 和 Firefox 82 以及更高的版本會優先使用 HTML 的 元素的 download 屬性而不是 Content-Disposition: inline 引數來處理下載。而 Firefox 的早期版本則優先使用檔頭資訊並內聯顯示內容。

作為多部分主體的檔頭

當使用 multipart/form-data 格式提交表單資料(HTTP 表單及 POST 請求)時,每個子部分(例如每個表單欄位和任何與欄位資料相關的檔案)都需要提供一個 Content-Disposition 檔頭,以提供相關資訊。檔頭的第一個引數始終為 form-data,並且還必須包含一個 name 引數來標識相關欄位。,以及可選的第三個引數 filename

Content-Disposition: form-data; name="fieldName"
Content-Disposition: form-data; name="fieldName"; filename="filename.jpg"

下面將通過程式碼演示通過設定content-type響應檔頭來實現圖片、pdf的線上預覽和下載,為返回的程式碼基本一樣所以封裝了一個公共方法,後面程式碼將通過呼叫這個公共方法來演示:

所用到的工具類程式碼:

import lombok.extern.slf4j.Slf4j;
import org.apache.tika.Tika;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;


@Component
@Slf4j
public class HttpUtil {
    public static ResponseEntity<?> getResponseEntity(byte[] fileContent, String contentDispositionType, String originalFileName){
        ResponseEntity.BodyBuilder responseEntity = ResponseEntity.*ok*();
        HttpHeaders httpHeaders = new HttpHeaders();
        Tika tika = new Tika();
        String mediaType = tika.detect(fileContent);
        httpHeaders.setContentType(MediaType.*parseMediaType*(mediaType));
        httpHeaders.setContentDisposition(ContentDisposition.*builder*(contentDispositionType)
                .filename(URLEncoder.encode(originalFileName)).build());
        httpHeaders.setCacheControl(CacheControl.noCache());
        //httpHeaders.setCacheControl(CacheControl.maxAge(10, TimeUnit.MINUTES));
        return responseEntity.headers(httpHeaders).body(fileContent);
    }
}

1、圖片預覽:

@GetMapping(value = "/image/review")
public ResponseEntity<?> imageReview() throws IOException {
    File file = new File("D:\\picture\\美女\\aa37a7be4196c07f43a3f776801d1b46.jpg");
    try (FileInputStream fileInputStream = new FileInputStream(file)) {
        byte[] buf = new byte[fileInputStream.available()];
        fileInputStream.read(buf);
        return HttpUtil.getResponseEntity(buf, "inline", "aa37a7be4196c07f43a3f776801d1b46.jpg");
    }
}

實現效果:

2、圖片下載:

@GetMapping(value = "/image/down")
public ResponseEntity<?> imageDown() throws IOException {
    File file = new File("D:\\picture\\美女\\aa37a7be4196c07f43a3f776801d1b46.jpg");
    try (FileInputStream fileInputStream = new FileInputStream(file)) {
        byte[] buf = new byte[fileInputStream.available()];
        fileInputStream.read(buf);
        return HttpUtil.getResponseEntity(buf, "attachment", "aa37a7be4196c07f43a3f776801d1b46.jpg");
    }
}

實現效果:

3、pdf預覽:

@GetMapping(value = "/pdf/review")
public ResponseEntity<?> pdfReview() throws IOException {
    File file = new File("D:\\書籍\\電子書\\其它\\自然哲學的數學原理.pdf");
    try (FileInputStream fileInputStream = new FileInputStream(file)) {
        byte[] buf = new byte[fileInputStream.available()];
        fileInputStream.read(buf);
        return HttpUtil.*getResponseEntity(buf, "inline", file.getName());
    }
}

實現效果:

4、pdf下載:

@GetMapping(value = "/pdf/down")
public ResponseEntity<?> pdfDown() throws IOException {
    File file = new File("D:\\書籍\\電子書\\其它\\自然哲學的數學原理.pdf");
    try (FileInputStream fileInputStream = new FileInputStream(file)) {
        byte[] buf = new byte[fileInputStream.available()];
        fileInputStream.read(buf);
        return HttpUtil.getResponseEntity(buf, "" +
                ""
                , file.getName());
    }
}

實現效果:

參考資料:Content-Disposition - HTTP | MDN