【问题标题】:How to solve encoding when piping file from NodeJs Cloud Function?从 NodeJs Cloud Function 传输文件时如何解决编码问题?
【发布时间】:2019-10-20 04:18:16
【问题描述】:

我正在尝试通过 nodeJS 云函数将 Firebase 存储桶中的文件传输到客户端(浏览器)。客户端将使用file-saver.js在浏览器上开始下载。

这适用于text/plain mime 类型,但会生成带有图像和 png 的损坏文件。问题在于编码,因为我可以看到到达客户端的数据未正确编码。

这是客户端带有图像的示例响应:

data: "�PNG↵↵IHDR%�*���sBIT|d�...

我应该如何正确地将文件传回以保持正确的编码?

这是当前的云功能:

const filesBucket = admin.storage().bucket(FILES_BUCKET_NAME);

function getFile(fileName, res){
  const filePath = fileName
  const file = filesBucket.file(filePath)

  res.setHeader('Content-Type', getMimeType(fileName));
  res.setHeader('Content-Disposition', 'attachment; filename='+fileName);

  file.createReadStream()
    .on('error', err => {
        // not good
    })
    .on('response', function(response) {
        // ok
    })
    .on('end', function() {
        // The file is fully downloaded.
    })
    .pipe(res); // pipe the file back to client
} 

这是客户端部分:

export const getFile = (filename) =>{
   ...
   axios.get(fileUrl, config)
     .then(resp => {
         downloadFile(resp.data, filename, getMimeType(filename))
     }).catch(err => {
         console.log("getCurrentUserFile | err", err)
         reject(err)
     })

function downloadFile(data, filename, mimeType){
    var blob = new Blob([data], {type: mimeType});
    FileSaver.saveAs(blob, filename);
}

【问题讨论】:

    标签: javascript node.js encoding stream pipe


    【解决方案1】:

    我不确定文件保护程序如何保存文件,但我能够通过以下设置下载文件,并且可能会对您有所帮助。 index.html

    <!DOCTYPE html>
    <html>
    
    <body onload="myFunction()">
    
        <h1>Hello World!</h1>
    
        <script>
            function myFunction() {
    
                var xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
    
                        var contentType = this.getResponseHeader('Content-Type')
                        var fileExtention;
                        if (contentType) {
    
                            fileExtention = contentType.split('/')[1]
    
                        }
    
                        //console.log(this.responseText)
                        var a = document.createElement("a");
                        document.body.appendChild(a);
                        a.style = "display: none";
    
                        var url = window.URL.createObjectURL(this.response);
                        a.href = url;
                        a.download = "demo." + fileExtention
                        a.click();
                        window.URL.revokeObjectURL(url);
                        a.remove();
                    }
                };
                xhttp.responseType = 'blob'
                xhttp.open("GET", "http://localhost:3000/getfile", true);
                xhttp.send();
    
            }
        </script>
    
    </body>
    
    </html>
    

    Nodejs:

    const express = require('express')
    const fs = require('fs')
    const app = express()
    const port = 3000
    
    app.use(express.static('public'))
    
    app.get('/getfile', (req, res) => {
        res.setHeader('Content-Type', 'image/png');
        //res.setHeader('Content-Disposition', 'attachment; filename='+'test.png');
        fs.createReadStream('./demo.png').pipe(res)
    })
    
    app.listen(port, () => console.log(`Example app listening on port ${port}!`))
    

    【讨论】:

    • 谢谢,但我尝试像您的示例一样从服务器传输本地 .png 或 .pdf 文件,并将其保存到文件保护程序中,如此处所示。 blog.jayway.com/2017/07/13/open-pdf-downloaded-api-javascript 仍然是相同的结果,下载的 .pdf 和 .png 文件已损坏。原件很好。
    • @KasparTr 我认为您没有为 Content-Type 传递正确的值。对于图像,它应该是image/imagetype,例如image/png,对于pdf application/pdf。
    • 此外,在下载时,您应该能够根据content-type 响应标头提供正确的文件扩展名
    • 不确定你最后的评论是什么意思,但我只是仔细检查了 MIME 类型,它们在服务器中设置正确。
    【解决方案2】:

    问题出在客户端,使用FileSaver.js 而没有任何编码。

    一旦我使用了它,它就起作用了:

    axios({
        url: fileUrl,
        method: 'GET',
        params:{...},
        responseType: 'blob', // <--important
    }).then((resp) => {
         const url = window.URL.createObjectURL(new Blob([resp.data]));
         const link = document.createElement('a');
         link.href = url;
         link.setAttribute('download', filename);
         document.body.appendChild(link);
         link.click();
    });
    

    Credit where credit it due

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 2020-02-27
      • 2020-12-25
      • 2019-11-09
      • 2019-10-15
      • 1970-01-01
      相关资源
      最近更新 更多