React中POST API下载含文件Zip文件夹为空问题求助
问题分析与解决方案
核心问题点
- Axios请求配置错误:POST请求的请求体需用
data字段,而非body(body是Fetch API的用法) - JSZip用法错误:若API返回的是已打包好的Zip Blob,无需二次创建Zip并添加文件夹;若返回多文件数据,需正确遍历添加文件
- 状态与拼写问题:缺失
buttonText状态定义,setCatergory拼写错误应为setCategory - 缺失必要导入:未导入
useState、Axios及UI组件
解决方案分两种场景
场景1:API返回已打包的Zip文件(Blob类型)
直接保存返回的Blob即可,无需JSZip二次处理:
import { useState } from "react"; import { saveAs } from "file-saver"; import Axios from "axios"; import TextField from '@mui/material/TextField'; import Button from '@mui/material/Button'; // 替换为你的API基础地址 const baseUrl = "https://your-api-domain.com"; function Download({ apiToken }) { const [category, setCategory] = useState(""); const [buttonText, setButtonText] = useState("Download"); const handleClick = () => { setButtonText("Downloading..."); const params = { subcategoryiid: category, }; Axios({ url: `${baseUrl}/cards/details`, method: "POST", responseType: "blob", headers: { Authorization: `Bearer ${apiToken}`, Accept: "application/json", "Content-Type": "application/json", }, // Axios使用data传递POST请求体 data: params, }) .then((res) => { // 直接保存API返回的Zip Blob saveAs(res.data, "project.zip"); setButtonText("Download"); }) .catch((err) => { console.error(err); setButtonText("Download"); }); }; return ( <div> <TextField className="box" placeholder="enter facility code" required value={category} onChange={(e) => setCategory(e.target.value)} /> <Button type="button" color="success" variant="contained" onClick={handleClick} > {buttonText} </Button> </div> ); } export default Download;
场景2:API返回多文件原始数据(如文件数组)
假设API返回JSON格式的文件列表(包含文件名、类型、Base64内容),需用JSZip逐个添加文件再打包:
import { useState } from "react"; import { saveAs } from "file-saver"; import JSZip from "jszip"; import Axios from "axios"; import TextField from '@mui/material/TextField'; import Button from '@mui/material/Button'; const baseUrl = "https://your-api-domain.com"; function Download({ apiToken }) { const [category, setCategory] = useState(""); const [buttonText, setButtonText] = useState("Download"); const handleClick = () => { setButtonText("Downloading..."); const params = { subcategoryiid: category, }; Axios({ url: `${baseUrl}/cards/details`, method: "POST", headers: { Authorization: `Bearer ${apiToken}`, Accept: "application/json", "Content-Type": "application/json", }, data: params, }) .then((res) => { const zip = new JSZip(); // 假设res.data是文件数组,每个元素结构:{name: "文件名称", content: "Base64字符串"} res.data.forEach(file => { zip.file(file.name, file.content, { base64: true }); }); return zip.generateAsync({ type: "blob" }); }) .then((zipBlob) => { saveAs(zipBlob, "project.zip"); setButtonText("Download"); }) .catch((err) => { console.error(err); setButtonText("Download"); }); }; return ( <div> <TextField className="box" placeholder="enter facility code" required value={category} onChange={(e) => setCategory(e.target.value)} /> <Button type="button" color="success" variant="contained" onClick={handleClick} > {buttonText} </Button> </div> ); } export default Download;
额外注意事项
- 先确认API返回的具体格式:通过控制台查看
res.data的类型和结构,选择对应场景的代码 - 确保
baseUrl配置正确,API请求能正常响应 - 若使用Material-UI组件,需确保已正确导入
TextField和Button
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

