簡體   English   中英

如何從瀏覽器 FETCH 觸發瀏覽器下載?

[英]How to trigger a browser download from a browser FETCH?

我正在開發一個項目,前端使用Vue.jsTypescript ,后端使用Java Spring

我的 java 控制器從數據庫中檢索給定的報告,然后將其復制到 HTML 響應中。 我希望瀏覽器下載 CSV,因此我在響應中添加了Content-disposition標頭。

     @GetMapping('/download')
     public void downloadCSV(HttpServletRequest response){
        Report r = reportService.findById(85);
        response.addHeader("Content-Disposition", "attachment; filename=myCSV.csv");
        response.setContentType("text/csv");

        try {
            InputStream stream = new ByteArrayInputStream(r.getDocument());
            IOUtils.copy(stream, response.getOutputStream());
            response.flushBuffer();
        } catch(Exception e) {...}
     }

我有 2 個按鈕:一個簡單的超鏈接標簽,帶有鏈接到download() 的href 和一個 b 按鈕(來自 bootstrap-vue),一旦點擊就會觸發download2()

   <a :href="download" role="button"> Download CSV </a>

   <b-button @click="event => download2()">
      Download CSV v2
   </b-button>
    get download(): string {
        return 'http://localhost:8080/download';
    }


    async download2() {
        const rHeaders = new Headers();
        rHeaders.append('Accept', 'text/csv');

        const configInit = RequestInit = {
           method: 'GET',
           headers: rHeaders
        };

        try {
            const res = await fetch('http://localhost:8080/download', configInit);
            return res.text();
        } catch (e) {...}
    }

現在,如果我單擊第一個按鈕“下載 csv”,則瀏覽器會正確下載 csv。 javascript 控制台打印以下內容:

Resource interpreted as Document but transferred with MIME type text/csv

並且響應體中沒有任何內容。

相反,如果我單擊第二個按鈕“下載 csv v2”,下載不會開始,但我的響應正文中有 csv。

在這里,兩者之間請求標頭的差異。

*Header*                   *Download csv*        *Download csv v2*
Sec-Fetch-Dest                document               empty
Sec-Fetch-Mode                navigate               cors
Sec-Fetch-User                   ?1                    -
Upgrade-Insecure-Requests        1                     -

其他標題相同。 即使我在 javascript 方法中設置它們,也無法更改這些標題; 它們保持不變。 有什么問題? 謝謝你。

我通過“模仿” <a>元素的行為找到了一個解決方案:

這樣,它可以正常工作:

async download2() {
    const configInit: RequestInit = {
        method: 'GET'
    };

    try {
       await fetch('http://localhost:8080/download', configInit)
          .then(response => response.blob())
          .then(blob => {
              const url = window.URL.createObjectURL(blob);
              const a = document.createElement('a');
              a.style.display = 'none';
              a.href = url;
              a.download = 'report.csv';
              document.body.appendChild(a);
              a.click();
              window.URL.revokeObjectURL(url);
          })
    } catch (e) {...}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM