簡體   English   中英

失敗 - 從 Amazon S3 下載 PDF 文件時出現網絡錯誤

[英]Getting Failed - Network Error while downloading PDF file from Amazon S3

目標:嘗試通過 NodeJS/VueJS 應用程序從 Amazon S3 下載 pdf 文件到我的本地計算機,而不在服務器的文件系統上創建文件。

服務器:NodeJs(v 18.9.0) Express (4.17.1)

中間件 function 從 S3 檢索文件並將 stream 轉換為 base64 字符串並將該字符串發送到客戶端:

const filename = 'lets_go_to_the_snackbar.pdf';

const s3 = new AWS.S3(some access parameters);
const params =  {
    Bucket: do_not_kick_this_bucket,
    Key: `yellowbrickroad/${filename}`
}

try {
    const data = await s3
        .getObject(params)
        .promise();

    const byte_string = Buffer.from(data.Body).toString('base64');
    res.send(byte_string);
} catch (err) {
    console.log(err);
}

客戶端:VueJS(v 3.2.33)

組件中的 Function 通過axios (v 0.26.1) GET 調用服務器接收字節字符串。 下載代碼如下:

getPdfContent: async function (filename) {
    const resp = await AxiosService.getPdf(filename) // Get request to server made here.

    const uriContent = `data:application/pdf;base64,${resp.data}`

    const link = document.createElement('a')
    link.href = uriContent
    link.download = filename
    document.body.appendChild(link)   // Also tried omitting this line along with...
    link.click()
    link.remove()                     // ...omitting this line
}

預期結果

  1. 瀏覽器打開 window 以允許選擇一個目錄作為文件的目標。
  2. 已選擇目錄。
  3. 文件已下載。
  4. 供應冰淇淋和月餅。

實際結果

  1. 瀏覽器打開 window 以允許選擇一個目錄作為文件的目標
  2. 已選擇目錄。
  3. 接收失敗 - 網絡錯誤消息。
  4. 好多哭...

瀏覽器:Chrome(版本 105.0.5195.125(官方構建)(x86_64))

在某處讀到 Chrome 會拒絕大於 4MB 的文件,所以我檢查了 S3 存儲桶,根據 Amazon S3,文件大小為 41.7KB。

在做了一些閱讀之后,提出了一個可能的解決方案,我試圖實施。 它涉及對 VueJs getPdfContent function 進行如下更改:

getPdfContent: async function (filename) {
    const resp = await AxiosService.getPdf(filename) // Get request to server made here.

    /**** This is the line that was changed ****/
    const uriContent = window.URL.createObjectURL(new Blob([resp.data], { type: 'application/pdf' } ))

    const link = document.createElement('a')
    link.href = uriContent
    link.download = filename
    document.body.appendChild(link)   // Also tried omitting this line along with...
    link.click()
    link.remove()                     // ...omitting this line
}

更新代碼的實際結果

  1. 瀏覽器打開 window 以允許選擇一個目錄作為文件的目標
  2. 已選擇目錄。
  3. PDF 文件已下載。
  4. 嘗試打開文件會產生以下消息:
The file “lets_go_to_the_snackbar.pdf” could not be opened.

It may be damaged or use a file format that Preview doesn’t recognize.

我可以使用 AWS S3 控制台直接從 S3 下載文件,打開文件沒有問題。

我已經閱讀了類似的帖子並嘗試實施他們的解決方案,但沒有發現任何樂趣。 如果有人可以,我將不勝感激

  1. 讓我知道我在實現目標的道路上要走的路
  2. 將我指向正確的道路。

預先感謝您的幫助。

在做了更多研究之后,我發現問題是我如何將數據從服務器返回到客戶端。 我不需要修改從 S3 服務接收到的數據。

服務器代碼:

let filename = req.params.filename;

    const params = {
        Bucket: do_not_kick_this_bucket,
        Key: `yellowbrickroad/${filename}`
    }
    try {
            const data = await s3
            .getObject(params)
            .promise();

        /* Here I did not modify the information returned */
        res.send(data.Body);
        res.end();

    } catch (err) {
        console.log(err);
    }

在客戶端,我的 VueJS 組件收到 Blob object 作為響應

客戶代碼:

async getFile (filename) {
      let response = await AuthenticationService.downloadFile(filename)

      const uriContent = window.URL.createObjectURL(new Blob([response.data]))

      const link = document.createElement('a')
      link.setAttribute('href', uriContent)
      link.setAttribute('download', filename)
      document.body.appendChild(link)
      link.click()
      link.remove()
    }

最終達到了目標; S3 上的文件可以直接下載到用戶的本地計算機,而無需應用程序在服務器上存儲文件。

我想提一下 Sunpun Sandaruwan 的回答,它給了我實現目標所需的最后線索。

暫無
暫無

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

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