FastAPI POST处理文件返回JSON无法在React显示,response.data为undefined
问题解决:React调用FastAPI接口后response.data为undefined及结果展示
问题原因分析
- Fetch API使用错误:
fetch返回的Response对象没有直接的data属性,必须通过.json()或.text()方法解析响应体才能获取实际数据。 - 后端返回格式问题:当前后端返回的是
DataFrame.to_json()生成的JSON字符串,FastAPI会将其作为纯文本返回(Content-Type为text/plain),前端需要额外解析才能转换成可操作的JSON对象。
解决方案
步骤1:优化FastAPI后端代码
将返回的JSON字符串改为直接返回Python字典,让FastAPI自动处理为标准JSON响应(Content-Type: application/json),简化前端解析流程:
@read_file.post("/upload_followers") async def create_upload_followers(followers_file: UploadFile, following_file: UploadFile): """ 处理Instagram格式的关注者和已关注列表,返回未回关的用户列表 """ try: if not (followers_file.content_type == 'application/json' and following_file.content_type == 'application/json'): raise ValueError('无效文件格式,请上传JSON文件。') # 读取并解析文件 followers_read = await followers_file.read() following_read = await following_file.read() followers_data = json.loads(followers_read) following_data = json.loads(following_read) # 提取用户名 valores_followers = [inner_item['value'] for item in followers_data for inner_item in item.get("string_list_data", [])] valores_following = [inner_item['value'] for item in following_data['relationships_following'] for inner_item in item.get("string_list_data", [])] # 数据处理 df_followers = pd.DataFrame(valores_followers, columns=['username']) df_following = pd.DataFrame(valores_following, columns=['username']) result1 = pd.merge(df_following, df_followers, on='username', how='left', indicator=True) result1['_merge'] = result1['_merge'].map({'left_only':'unfollow', 'both':'keep'}) df_result = result1[result1['_merge'] == 'unfollow'] # 生成本地文件(可选) df_result.to_json('file.json') # 返回字典格式,FastAPI自动转为JSON响应 return df_result.to_dict('records') except Exception as e: return JSONResponse(content={'error': str(e)}, status_code=400)
步骤2:修改React前端代码
新增状态存储返回结果,正确解析Fetch响应,并渲染结果列表:
import { useState } from "react"; function FileForm() { const [fileFollowers, setFileFollowers] = useState(null); const [fileFollowing, setFileFollowing] = useState(null); const [unfollowList, setUnfollowList] = useState([]); // 存储未回关用户列表 const handleFileInputChangeFollowers = (event) => { setFileFollowers(event.target.files[0]); }; const handleFileInputChangeFollowing = (event) => { setFileFollowing(event.target.files[0]); }; const handleSubmit = async (event) => { event.preventDefault(); if (!fileFollowers || !fileFollowing) return; const formData = new FormData(); formData.append('followers_file', fileFollowers); formData.append('following_file', fileFollowing); try { const endpoint = "http://localhost:8000/upload_followers"; const response = await fetch(endpoint, { method: "POST", body: formData }); if (response.ok) { console.log("文件上传成功!"); // 解析标准JSON响应 const data = await response.json(); console.log("未回关用户列表:", data); setUnfollowList(data); // 将结果存入状态 } else { const errorData = await response.json(); console.error("文件上传失败:", errorData.error); } } catch(error) { console.error("请求出错:", error); } }; return ( <div style={{ maxWidth: 800, margin: '2rem auto', padding: '0 1rem' }}> <h1>上传Instagram关注数据</h1> <form onSubmit={handleSubmit}> <div style={{ marginBottom: "20px" }}> <input type="file" onChange={handleFileInputChangeFollowers} accept=".json" // 限制仅上传JSON文件 required /> <span style={{ margin: '0 1rem' }}>关注者文件</span> <input type="file" onChange={handleFileInputChangeFollowing} accept=".json" required /> <span>已关注列表文件</span> </div> <button type="submit" disabled={!fileFollowers || !fileFollowing}> 上传并分析 </button> </form> {fileFollowers && <p>已选择关注者文件:{fileFollowers.name}</p>} {fileFollowing && <p>已选择已关注列表文件:{fileFollowing.name}</p>} {/* 渲染未回关用户列表 */} {unfollowList.length > 0 && ( <div style={{ marginTop: '2rem' }}> <h2>未回关你的用户(共{unfollowList.length}人)</h2> <ul style={{ listStyle: 'none', padding: 0 }}> {unfollowList.map((item, index) => ( <li key={index} style={{ padding: '0.5rem', borderBottom: '1px solid #eee' }}> {item.username} </li> ))} </ul> </div> )} </div> ); } export default FileForm;
兼容旧后端代码的方案
如果不想修改后端,前端需要先读取响应文本再解析JSON:
const text = await response.text(); const data = JSON.parse(text);
内容的提问来源于stack exchange,提问作者Simon Londoño R
相关产品推荐
相关产品推荐

