如何使用jQuery getJSON获取后端IPFS文件哈希并更新前端innerHTML
文件上传IPFS功能代码修复
现有代码核心问题
- 逻辑冲突:同时写了浏览器端直连IPFS上传、后端代理上传两套逻辑,互相干扰
- 请求方式错误:文件上传使用
GET请求搭配$.getJSON,无法传输二进制文件内容,且GET请求没有请求体,后端req.files永远拿不到值 - 异步语法错误:
- 前端
IpfsCore.create()是异步方法,未加await就调用后续方法会直接抛出异常 - 后端
saveFile方法没有return返回值,且混用回调风格的ipfs.add和async/await,接口无法返回真实的文件哈希
- 前端
- 选择器错误:jQuery获取元素写为
$('file'),缺少ID选择器前缀#,无法选中文件输入框 - 文件处理错误:直接
JSON.stringify(file)序列化File对象,会丢失二进制内容,最终存到IPFS的只是文件元数据字符串,不是真实文件 - 事件绑定逻辑混乱:
clickme方法里重复绑定change事件,存在重复触发风险
修正后代码
后端 index.js
首先需要安装文件上传处理依赖:
npm install express-fileupload
修正后的服务端代码:
const express = require('express'); const fileUpload = require('express-fileupload'); const app = express(); // 注册文件上传中间件,支持最大500MB文件 app.use(fileUpload({ limits: { fileSize: 500 * 1024 * 1024 }, })); // 上传接口改为POST方法 app.post('/upload', async (req, res) => { try { if (!req.files || !req.files.file) { return res.status(400).json({ code: 400, msg: '未接收到上传文件' }); } const file = req.files.file; // 直接传文件buffer给IPFS,不要JSON序列化 const fileHash = await saveFile(file.data); res.json({ code: 200, hash: fileHash, fileType: file.mimetype, fileName: file.name }); } catch (err) { console.log('上传失败:', err); res.status(500).json({ code: 500, msg: '上传失败' }); } }) async function saveFile(fileBuffer) { // 注意:这里需要提前初始化你服务端的ipfs节点实例,替换为你自己的初始化逻辑 const result = await ipfs.add(fileBuffer); console.log('文件上传IPFS成功,CID:', result.cid.toString()); return result.cid.toString(); } app.listen(3000, () => { console.log('服务运行在3000端口'); })
前端 index.ejs
这里统一走后端代理上传逻辑,移除冗余的前端IPFS初始化代码,修正请求和DOM更新逻辑:
<!-- 不需要前端引ipfs-core,走后端上传即可 --> <input type="file" id="file" accept="image/*,video/*,audio/*,application/pdf"> <div>文件名:<span id="fileNameOutput"></span></div> <div>IPFS哈希:<span id="ipfs"></span></div> <div id="filePreview"></div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> <script> // 页面加载完成后绑定事件 $(function() { $('#file').on('change', readfichier); }) async function readfichier(e) { const file = e.target.files[0]; if (!file) return; // 显示文件名 $('#fileNameOutput').text(file.name); $('#ipfs').text('上传中...'); $('#filePreview').html(''); // 构造FormData传文件,不用GET请求 const formData = new FormData(); formData.append('file', file); try { // 用POST请求上传,不要用$.getJSON const res = await $.ajax({ url: '/upload', type: 'POST', data: formData, processData: false, contentType: false, dataType: 'json' }); if (res.code === 200) { // 更新哈希到页面 $('#ipfs').text(res.hash); // 渲染文件预览 renderPreview(res.hash, res.fileType); } else { $('#ipfs').text('上传失败:' + res.msg); } } catch (err) { $('#ipfs').text('上传请求失败'); console.log(err); } } // 多格式文件预览渲染 function renderPreview(cid, fileType) { // 替换为你自己部署的IPFS网关地址 const gatewayUrl = `/ipfs/${cid}`; let previewHtml = ''; if (fileType.startsWith('image/')) { previewHtml = `<img src="${gatewayUrl}" style="max-width: 100%;" alt="预览图">`; } else if (fileType.startsWith('video/')) { previewHtml = `<video src="${gatewayUrl}" controls style="max-width: 100%;"></video>`; } else if (fileType.startsWith('audio/')) { previewHtml = `<audio src="${gatewayUrl}" controls></audio>`; } else if (fileType === 'application/pdf') { previewHtml = `<embed src="${gatewayUrl}" type="application/pdf" width="100%" height="600px">`; } else { previewHtml = `<a href="${gatewayUrl}" target="_blank">点击下载文件</a>`; } $('#filePreview').html(previewHtml); } </script>
注意事项
- 服务端需要提前完成IPFS节点初始化,确保
ipfs实例可用 - 生产环境建议自己部署IPFS网关,不要依赖公共网关,保证文件访问稳定性
- 如果需要前端直连IPFS上传,只需要把后端上传逻辑替换为前端正确初始化IPFS节点后上传即可,不需要调用后端接口,两种方案二选一即可,不要同时使用
内容的提问来源于stack exchange,提问作者JackDonMcLovin
相关产品推荐
相关产品推荐

