【问题标题】:How can I create a button which Fetches image from API and download to the local with using ReactJs如何创建一个从 API 获取图像并使用 ReactJs 下载到本地的按钮
【发布时间】:2021-07-02 19:42:32
【问题描述】:

我需要一个将图像下载到本地的按钮。但是这些图片来自 Unsplash API。

我找到了一个 HTML download attribute, LIVE DEMO

<p>Click on the image to download it:<p>
<a href="/images/myw3schoolsimage.jpg" download>
  <img src="/images/myw3schoolsimage.jpg" alt="W3Schools" width="104" height="142">
</a>

但是如果我想在 React 中使用这个方法是行不通的。原因是我想从 Unsplash API 下载的图像因此无法正常工作!但是,如果我尝试下载属于我的项目目录的本地图像,它就成功了!

import style from "./style.module.css";
import cn from "classnames";
import { BiDownArrowAlt, BiPlus } from "react-icons/bi";

import logo from "../../assets/images/Logo.png";

const ImageCard = ({ image }) => {
    return (
        <div className={style.image}>
            {/* {  Download Button } */}
            <a href={logo} download target="_blank">
                <span className={cn(style.button, style.downloadButton)}>
                    <BiDownArrowAlt className={style.downloadIcon} />
                </span>
            </a>
        </div>
    );
};

这可行,但我的照片来自 API。

我在 StackOverflow 中搜索了这个主题,我找到了 this question。但是这种方法是行不通的。这会下载图像,但图像无法正常工作。

import style from "./style.module.css";
import cn from "classnames";

import { BiDownArrowAlt, BiPlus } from "react-icons/bi";

const download = (e) => {
    console.log(e.target.href);
    fetch(e.target.href, {
        method: "GET",
        headers: {},
    })
        .then((response) => {
            response.arrayBuffer().then(function (buffer) {
                const url = window.URL.createObjectURL(new Blob([buffer]));
                const link = document.createElement("a");
                link.href = url;
                link.setAttribute("download", "image.png"); //or any other extension
                document.body.appendChild(link);
                link.click();
            });
        })
        .catch((err) => {
            console.log(err);
        });
};

const ImageCard = ({ image }) => {
    return (
        <div className={style.image}>
            {/* {  Download Button } */}
            <a
                href={image.links.download}
                download
                onClick={(e) => download(e)}
                target="_blank"
            >
                <span className={cn(style.button, style.downloadButton)}>
                    <BiDownArrowAlt className={style.downloadIcon} />
                </span>
            </a>
    );
};

export default ImageCard;

请帮助我解决这个问题!

【问题讨论】:

    标签: javascript html reactjs downloadfile


    【解决方案1】:

    这里有一个香草 javascript 的解决方案

    const IMG_URL = "https://media.gettyimages.com/photos/closeup-network-space-picture-id1013942164?s=612x612";
    
    function toDataURL(url) {
      return fetch(url).then((response) => {
              return response.blob();
          }).then(blob => {
              return window.URL.createObjectURL(blob);
          });
    }
    
    async function download() {    
        const a = document.createElement("a");
        a.href = await toDataURL(IMG_URL);
        a.download = "myImage.png";
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }
    
    const link = document.querySelector('#link');
    
    link.addEventListener('click', () => {
      download()
    })
    &lt;a href="#" id="link"&gt;Download&lt;/a&gt;

    这里被屏蔽了,但是你可以看到它在 fiddle https://jsfiddle.net/f5061vbc/1/ 上工作

    【讨论】:

      【解决方案2】:

      我认为这个image.links.download 可能缺少图像 URL 的主机域部分。

      考虑在其前面添加主机域,使其看起来像这样。

      href={`IMAGE_HOST_DOMAIN/${image.links.download}`}
      

      由于图像来自 Unsplash API,因此很可能是 Unsplash 主机域

      编辑:

      重构您的下载功能,如下所示:

      const download = async (e) => {
        try {
          const blob = await fetch(e.target.href).then(res => res.blob())
          const url = window.URL.createObjectURL(blob);
          const link = document.createElement("a");
          link.href = url;
          link.download = "image.png"; //or any other extension
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        } catch {
          console.error('Unable to download image...')
        }
      };
      

      然后像这样在a 标签中触发onClick

      <a
       href={image.urls.raw}
       download
       onClick={download}
      >
      

      【讨论】:

      • 是的,你是对的,我将image.links.download 更改为image.urls.raw,它提供了一个伪装图像 URL,但注意关于下载图像点的更改
      • 如果你这样做了,那么你就不再需要你拥有的下载功能了。所以删除onClick={(e) =&gt; download(e)}
      • 我只是删除了那部分并下载了代码顶部的功能,但仍然无法正常工作
      • 点击下载链接时究竟会发生什么?
      • 只需转到新标签并在此处打开该图像
      猜你喜欢
      • 2018-10-24
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 2018-11-16
      相关资源
      最近更新 更多