React:下载按钮有效,但下载的文件为空

问题描述 投票:0回答:1

我是编程新手,在 React 文件中创建下载按钮时遇到了一些困难。简而言之,我使用 Kotlin Spring Boot 构建了一个 API,并使用 JSON 对其进行了测试。现在,我尝试通过 React 使用这个 API。

我的困难在于下载功能。该按钮下载文件,但它显示为空。但是,当我检查该元素时,该文件及其所有内容都会出现在“源控制台”(Safari) 中,允许我保存它。

您能帮我解释一下为什么下载按钮不显示 PDF 内容吗?我该怎么做才能解决这个问题?

有关我的 GitHub 的更多信息:https://github.com/raysatownsend/Consumindo_Api_React/blob/main/src/pages/Books/index.js

谢谢你!

期待对我的代码说明的帮助。可能是错的。

我的代码如下:

导出默认函数 Books() {

const [books, setBooks] = useState([]);
const [page, setPage] = useState(0);
const [files, setFiles] = useState([]);

const navigate = useNavigate();

const accessToken = localStorage.getItem("accessToken");
const username = localStorage.getItem("username");

const authorization = {
    headers:{
        Authorization: `Bearer ${accessToken}`
    }
};

const contentType = {
    headers: {
        "Content-Type": "application/octet-stream",
        "Content-Type": "application/pdf"
    }
}

const responseType = {
    headers: {
        responseType: 'blob',
    }
}

useEffect(() => {
    fetchMoreBooks();
}, [accessToken])

async function fetchMoreBooks() {
    const response = await api.get(`api/books/v1?page=${page}&size=8&direction=asc`, authorization)
    setBooks([...books, ...response.data._embedded.authorVOList]);
    setPage(page + 1);
}

async function editBook(id) {
    try {
        navigate(`/books/book/new/${id}`);
    } catch (error) {
        alert("Edit book failed, please try again.")
    }
}

async function downloadBook() {
    try {
        const response = await api.get("api/file/v1/downloadFile/PRESSMAN_Engenharia_de_software_Uma_Abor.pdf", authorization, contentType, responseType)
        // Create a Blob object from the response data
        const blob = new Blob([...files, ...response.data], { type: response.headers["Content-Type"] });

        // Create a temporary anchor element
        const downloadLink = document.createElement('a');
        downloadLink.href = window.URL.createObjectURL(blob);
        downloadLink.setAttribute('download', 'PRESSMAN_Engenharia_de_software_Uma_Abor.pdf'); // Set the download attribute with desired filename
        document.body.appendChild(downloadLink);
        // Trigger the download by programmatically clicking the anchor element
        downloadLink.click();

        // Cleanup
        window.URL.revokeObjectURL(downloadLink.href);
    } catch (error) {
        alert("ERROR: Can't download choosen item, please try again.");
    }

}

async function deleteBook(id) {
    try {
        await api.delete(`api/books/v1/${id}`, authorization)
        setBooks(books.filter(book => book.id !== id))
    } catch (error) {
        alert("ERROR: Can't delete choosen item, please try again.")
    }
}

async function logout() {
    try {
        localStorage.clear()
        navigate("/")
    } catch (error) {
        alert("Logout failed, please try again.")
    }
}


return (
    <div className="book-container">
        <header>
            <img src={logoImage} alt="Logo" />
            <span>Bem-Vindo, <strong>{username.toUpperCase()}</strong>!</span>
            <Link className="button" to="book/new/0">Add New Book</Link>
            <button onClick={logout} type="button">
                <FiPower size={18} color='#251FC5'/>
            </button>
        </header>

        <h1>Registered Books</h1>
        <ul>
            {books.map(book => (
                <li key={book.id}>
                <strong>Title:</strong>
                <p>{book.title}</p>
                <strong>Author:</strong>
                <p>{book.author}</p>
                <strong>Price:</strong>
                <p>{Intl.NumberFormat('pt-BR', {style: 'currency', currency: 'BRL'}).format(book.price)}</p>
                <strong>Release Date:</strong>
                <p>{Intl.DateTimeFormat('pt-BR').format(new Date(book.launchDate))}</p>

                <button onClick={() => editBook(book.id)} type="button">
                    <FiEdit size={20} color="#251FC5"/>
                </button>
                <button onClick={() => downloadBook()} type="button">
                    <FiDownload size={20} color="#251FC5"/>
                </button>
                <button onClick={() => deleteBook(book.id)} type="button">
                    <FiTrash2 size={20} color="#251FC5"/>
                </button>
            </li>
            ))}
        </ul>
        <button className="button" onClick={fetchMoreBooks} type="button">Load more</button>
    </div>
);

}

reactjs file download
1个回答
0
投票

代码很多,但我发现你的

downloadBook
函数不太正确。你在那里做了不必要的步骤。
我还没有阅读你的完整代码,所以我没有看到
files
数组中的要点。

这是简化的工作功能,您可以根据您的需要进行调整:

async function downloadBook() {
  // fetching data from a url, getting an response if everything is ok
  // I use simple fetch here (not axios, etc)
  const response = await fetch('your url');

  // now creating a blob from response, it should have correct type automatically
  const resBlob = await response.blob();

  // Create a temporary anchor element
  const downloadLink = document.createElement('a');
  downloadLink.href = window.URL.createObjectURL(resBlob);
  downloadLink.setAttribute('download', 'PRESSMAN_Engenharia_de_software_Uma_Abor.pdf'); // Set the download attribute with desired filename
  document.body.appendChild(downloadLink);
  // Trigger the download by programmatically clicking the anchor element
  downloadLink.click();

  // Cleanup
  window.URL.revokeObjectURL(downloadLink.href);
}
© www.soinside.com 2019 - 2024. All rights reserved.