Javascript 如何使用 window.fetch 下载文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32545632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:34:57  来源:igfitidea点击:

How can I download a file using window.fetch?

javascriptfetchfetch-api

提问by syg

If I want to download a file, what should I do in the thenblock below?

如果我想下载一个文件,我应该在then下面的块中做什么?

function downloadFile(token, fileId) {
  let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
  return fetch(url, {
    method: 'GET',
    headers: {
      'Authorization': token
    }
  }).then(...);
}

Note the codes are in client-side.

注意代码在客户端。

采纳答案by syg

I temporarily solve this problem by using download.jsand blob.

我通过使用download.jsblob.

let download = require('./download.min');

...

function downloadFile(token, fileId) {
  let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
  return fetch(url, {
    method: 'GET',
    headers: {
      'Authorization': token
    }
  }).then(function(resp) {
    return resp.blob();
  }).then(function(blob) {
    download(blob);
  });
}

It's working for small files, but maybe not working for large files. I think I should dig Streammore.

它适用于小文件,但可能不适用于大文件。我想我应该更多地挖掘Stream

回答by Mariusz Pawelski

EDIT: syg answer is better. Just use downloadjslibrary.

编辑:syg 答案更好。只需使用downloadjs库。

The answer I provided works well on Chrome, but on Firefox and IE you need some different variant of this code. It's better to use library for that.

我提供的答案在 Chrome 上运行良好,但在 Firefox 和 IE 上,您需要此代码的一些不同变体。最好为此使用库。



I had similar problem (need to pass authorization header to download a file so thissolution didn't helped).

我有类似的问题(需要通过授权标头来下载文件,所以这个解决方案没有帮助)。

But based on thisanswer you can use createObjectURLto make browser save a file downloaded by Fetch API.

但是基于答案,您可以使用createObjectURL浏览器保存由 Fetch API 下载的文件。

getAuthToken()
    .then(token => {
        fetch("http://example.com/ExportExcel", {
            method: 'GET',
            headers: new Headers({
                "Authorization": "Bearer " + token
            })
        })
        .then(response => response.blob())
        .then(blob => {
            var url = window.URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.download = "filename.xlsx";
            document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox
            a.click();    
            a.remove();  //afterwards we remove the element again         
        });
    });

回答by Zibri

function download(dataurl, filename) {
  var a = document.createElement("a");
  a.href = dataurl;
  a.setAttribute("download", filename);
  a.click();
  return false;
}

download("data:text/html,HelloWorld!", "helloWorld.txt");

or:

或者:

function download(url, filename) {
fetch(url).then(function(t) {
    return t.blob().then((b)=>{
        var a = document.createElement("a");
        a.href = URL.createObjectURL(b);
        a.setAttribute("download", filename);
        a.click();
    }
    );
});
}

download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");

回答by Lucas Matos

This is more shorter and efficient, no libraries only fetch API

这更短更高效,没有库只获取 API

const url ='http://sample.example.file.doc'
const authHeader ="Bearer 6Q************" 

const options = {
  headers: {
    Authorization: authHeader
  }
};
 fetch(url, options)
  .then( res => res.blob() )
  .then( blob => {
    var file = window.URL.createObjectURL(blob);
    window.location.assign(file);
  });

回答by Daniel

Using dowloadjs. This will parse the filename from the header.

使用下载js。这将从标题中解析文件名。

fetch("yourURL", {
    method: "POST",
    body: JSON.stringify(search),
    headers: {
        "Content-Type": "application/json; charset=utf-8"
    }
    })
    .then(response => {
        if (response.status === 200) {
            filename = response.headers.get("content-disposition");
            filename = filename.match(/(?<=")(?:\.|[^"\])*(?=")/)[0];
            return response.blob();
        } else {
        return;
        }
    })
    .then(body => {
        download(body, filename, "application/octet-stream");
    });
};

回答by Michael Hobbs

Here is an example using node-fetch for anyone that finds this.

这是一个使用 node-fetch 的示例,供任何发现它的人使用。

reportRunner({url, params = {}}) {
    let urlWithParams = `${url}?`
    Object.keys(params).forEach((key) => urlWithParams += `&${key}=${params[key]}`)
    return fetch(urlWithParams)
        .then(async res => ({
            filename: res.headers.get('content-disposition').split('filename=')[1],
            blob: await res.blob()
        }))
        .catch(this.handleError)
}

回答by Maddocks

I tried window.fetch but that ended up being complicated with my REACT app

我试过 window.fetch 但结果我的 REACT 应用程序变得很复杂

now i just change window.location.href and add query params like the jsonwebtokenand other stuff.

现在我只是更改 window.location.href 并添加查询参数,如jsonwebtokenother stuff


///==== client side code =====
var url = new URL(`http://${process.env.REACT_APP_URL}/api/mix-sheets/list`);
url.searchParams.append("interval",data.interval);
url.searchParams.append("jwt",token)

window.location.href=url;

// ===== server side code =====

// on the server i set the content disposition to a file
var list = encodeToCsv(dataToEncode);
res.set({"Content-Disposition":`attachment; filename=\"FileName.csv\"`});
res.status(200).send(list)

the end results actually end up being pretty nice, the window makes request and downloads the file and doesn't event switch move the page away, its as if the window.location.hrefcall was like a lowkey fetch()call.

最终结果实际上非常好,窗口发出请求并下载文件,并且没有事件开关将页面移开,就好像window.location.href呼叫就像一个低调的fetch()呼叫。

回答by Yuci

As per some of the other answers, you can definitely use window.fetch and download.jsto download a file. However, using window.fetch with blob has the restriction on memory imposed by the browser, and the download.js also has its compatibility restrictions.

根据其他一些答案,您绝对可以使用 window.fetch 和download.js下载文件。但是,使用window.fetch 和blob 有浏览器对内存的限制,而download.js 也有其兼容性限制

If you need to download a big-sized file, you don't want to put it in the memory of the client side to stress the browser, right? Instead, you probably prefer to download it via a stream. In such a case, using an HTML link to download a file is one of the best/simplest ways, especially for downloading big-sized files via a stream.

如果你需要下载一个大文件,你不想把它放在客户端的内存中给浏览器带来压力,对吧?相反,您可能更喜欢通过流下载它。在这种情况下,使用 HTML 链接下载文件是最好/最简单的方法之一,尤其是通过流下载大文件。

Step One:create and style a link element

第一步:创建链接元素并为其设置样式

You can make the link invisible but still actionable.

您可以使链接不可见,但仍可操作。

HTML:

HTML:

<a href="#" class="download-link" download>Download</a>

CSS:

CSS:

.download-link {
  position: absolute;
  top: -9999px;
  left: -9999px;
  opacity: 0;
}

Step Two:Set the hrefof the link, and trigger the clickevent

第二步:设置href链接的,并触发click事件

JavaScript

JavaScript

let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;

const downloadLink = document.querySelector('.download-link')
downloadLink.href = url + '&ts=' + new Date().getTime() // Prevent cache
downloadLink.click()

Note: you can dynamically generate the link element if necessary.

注意:如有必要,您可以动态生成链接元素。