React项目中获取CSV文件对象并实现CSV转本地JSON文件的技术咨询
Solution: Add CSV to JSON Export in React
Hey there! You're totally right about not being able to use fs in the browser—we need to lean into browser-native APIs to handle the file download. Let's modify your existing code to add the JSON export feature without breaking your current table display.
Here's the updated code with explanations of the key changes:
import React, { useState } from 'react'; import * as XLSX from 'xlsx'; import DataTable from 'react-data-table-component'; function App() { const [columns, setColumns] = useState([]); const [data, setData] = useState([]); // 新增状态存储转换后的JSON字符串 const [jsonData, setJsonData] = useState(null); // process CSV data const processData = dataString => { const dataStringLines = dataString.split(/\r\n|\n/); const headers = dataStringLines[0].split(/,(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/); const list = []; for (let i = 1; i < dataStringLines.length; i++) { const row = dataStringLines[i].split(/,(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/); if (headers && row.length === headers.length) { const obj = {}; for (let j = 0; j < headers.length; j++) { let d = row[j]; if (d.length > 0) { if (d[0] === '"') d = d.substring(1, d.length - 1); if (d[d.length - 1] === '"') d = d.substring(0, d.length - 1); // 修正原代码的substring参数错误 } if (headers[j]) { obj[headers[j]] = d; } } // remove the blank rows if (Object.values(obj).filter(x => x).length > 0) { list.push(obj); } } } // prepare columns list from headers const columns = headers.map(c => ({ name: c, selector: c, })); setData(list); setColumns(columns); // 将处理好的数组转换为格式化的JSON字符串并存储 setJsonData(JSON.stringify(list, null, 2)); } // 新增JSON下载函数 const downloadJson = () => { if (!jsonData) return; // 创建Blob对象存储JSON内容 const blob = new Blob([jsonData], { type: 'application/json' }); // 生成临时下载URL const downloadUrl = URL.createObjectURL(blob); // 创建a标签触发下载 const link = document.createElement('a'); link.href = downloadUrl; link.download = 'csv-to-json-result.json'; // 自定义下载文件名 document.body.appendChild(link); link.click(); // 清理临时URL避免内存泄漏 URL.revokeObjectURL(downloadUrl); document.body.removeChild(link); } // handle file upload function handleFileUpload(e) { const file = e.target.files[0]; const reader = new FileReader(); reader.onload = (evt) => { /* Parse data */ const bstr = evt.target.result; const wb = XLSX.read(bstr, { type: 'binary' }); /* Get first worksheet */ const wsname = wb.SheetNames[0]; const ws = wb.Sheets[wsname]; /* Convert array of arrays */ const data = XLSX.utils.sheet_to_csv(ws, { header: 1 }); processData(data); }; reader.readAsBinaryString(file); } return ( <div style={{ padding: '2rem' }}> <input type="file" accept=".csv,.xlsx,.xls" onChange={handleFileUpload} /> {/* 只有当JSON数据存在时才显示下载按钮 */} {jsonData && ( <button onClick={downloadJson} style={{ margin: '1rem 0', padding: '0.5rem 1rem' }}> 下载JSON文件 </button> )} <DataTable pagination highlightOnHover columns={columns} data={data} /> </div> ); } export default App;
Key Changes Explained:
- Added
jsonDataState: Stores the formatted JSON string of your CSV data once it's processed, so we can reuse it for download. - Updated
processData: After generating thelistof objects, we convert it to a human-readable JSON string and save it to state. - New
downloadJsonFunction: Uses the browser'sBlobAPI to create a JSON file in memory, generates a temporary download URL, and triggers the download via a dynamically created<a>tag. We also clean up the temporary URL afterward to avoid memory leaks. - Download Button: Only renders when we have valid JSON data, so users can't click it before uploading a file.
Quick Fix Note:
I also fixed a small bug in your original processData function where the substring for removing trailing quotes was using incorrect parameters (d.substring(d.length - 2, 1) would return an empty string for most cases—changed it to d.substring(0, d.length - 1)).
内容的提问来源于stack exchange,提问作者xiongzhong li




