如何获取<input>文件真实路径?Pinata IPFS上传假路径问题
解决Pinata IPFS文件上传的假路径问题
问题核心是浏览器出于安全机制,不会暴露用户本地文件的真实路径,input[type="file"].value返回的C:\fakepath\xxx是浏览器伪造的路径,无法直接用于后端的fs.createReadStream读取。正确的做法是传输文件内容而非路径,具体方案如下:
1. 前端修改:传输文件内容而非路径
不要获取file.value,而是直接获取<input>选中的File对象,通过Socket.IO传输文件内容(支持二进制或FormData格式):
<body> <input type="file" id="file-upload"> <script src="/socket.io/socket.io.js"></script> <script> const socket = io(); const fileInput = document.getElementById("file-upload"); fileInput.addEventListener("change", (e) => { const selectedFile = e.target.files[0]; if (!selectedFile) return; // 方式:用FormData封装文件,直接通过Socket.IO发送 const formData = new FormData(); formData.append("uploadFile", selectedFile); socket.emit("send-file-to-pinata", { fileName: selectedFile.name, fileData: formData }); }); </script> </body>
2. 后端修改:接收文件内容并上传到Pinata
后端不再接收路径,而是接收前端传来的文件内容,将其转为可读流或直接用Buffer封装进FormData,再调用Pinata API:
const io = require('socket.io')(server); const axios = require('axios'); const FormData = require('form-data'); const fs = require('fs'); const path = require('path'); const os = require('os'); // 处理Socket.IO传来的文件 io.on('connection', (socket) => { socket.on('send-file-to-pinata', async ({ fileName, fileData }) => { try { // 临时存储文件(可选,也可直接用Buffer处理) const tempFilePath = path.join(os.tmpdir(), `${Date.now()}-${fileName}`); const writeStream = fs.createWriteStream(tempFilePath); // 解析FormData并写入临时文件 fileData.pipe(writeStream); await new Promise((resolve, reject) => { writeStream.on('finish', resolve); writeStream.on('error', reject); }); // 调用上传函数 const uploadResult = await pinToPinata( '你的Pinata API Key', '你的Pinata Secret Key', tempFilePath, fileName ); // 删除临时文件 fs.unlinkSync(tempFilePath); socket.emit('upload-success', uploadResult.data); } catch (err) { socket.emit('upload-error', err.message); } }); }); // 优化后的Pinata上传函数 async function pinToPinata(apiKey, secretKey, filePath, fileName) { const url = 'https://api.pinata.cloud/pinning/pinFileToIPFS'; const formData = new FormData(); // 添加文件流到FormData formData.append('file', fs.createReadStream(filePath), { filename: fileName }); return axios.post(url, formData, { maxBodyLength: Infinity, headers: { // 自动生成Content-Type和boundary,避免手动设置出错 ...formData.getHeaders(), pinata_api_key: apiKey, pinata_secret_api_key: secretKey } }); }
关键说明
- 浏览器安全限制:永远不要试图获取本地文件的真实路径,这是浏览器的安全保护机制,无法绕过。
- 文件传输方式:除了FormData,也可以用
FileReader将文件转为ArrayBuffer后传输,后端再转为Buffer处理。 - 临时文件处理:如果不想用临时文件,可直接将前端传来的Buffer添加到FormData中(
formData.append('file', buffer, { filename: fileName })),省去磁盘IO步骤。
内容的提问来源于stack exchange,提问作者user11855540
相关产品推荐
相关产品推荐

