如何通过Fetch API配合Rails ActiveStorage实现媒体文件上传及关联数据存储
问题根因
你当前遇到的核心问题是JSON格式的请求无法传输二进制文件,浏览器不支持将文件对象直接序列化为JSON字符串,所以后端接收到的mediadata参数为空,自然无法存储媒体文件。
修复步骤
1. 修复JS中收集文件的冗余逻辑
原来的保存按钮点击事件中allimage数组重复push了两次数据,导致后续取值错误,修改对应代码:
savebtn.addEventListener('click',(event)=>{ var position = [] var dimension = [] let allSections =[] let filesId = [] let layout_id = window.location.href.split("/layouts/")[1] let sections = document.querySelectorAll('.section') var inputElementArr = document.querySelectorAll('.file-input') var allimage = [] // 修复后的遍历逻辑 sections.forEach((section)=>{ const fileInput = document.getElementById("input"+section.id.split("section")[1]) const file = fileInput.files.length > 0 ? fileInput.files[0] : null position.push($("#"+section.id).position()) dimension.push(($("#"+section.id).height())*$("#"+section.id).width()) allSections.push(section.id) allimage.push(file) }) storeData(allSections,position,dimension,allimage,layout_id); })
2. 重写POST请求逻辑,改用FormData传输数据
原来的POST请求使用JSON格式传输,不支持文件二进制内容,修改post函数:
function post(url, body) { var token = $('meta[name="csrf-token"]').attr('content'); // 构造FormData对象用于传输文件 const formData = new FormData(); // 按照Rails强参数要求构造嵌套的section参数 Object.keys(body).forEach(key => { if (key === 'mediadata' && body[key]) { formData.append(`section[${key}]`, body[key]); } else { formData.append(`section[${key}]`, body[key]); } }); const requestOptions = { method: 'POST', headers: { // 不要手动设置Content-Type,浏览器会自动生成带boundary的正确值 'X-CSRF-Token': token }, body: formData, credentials: 'same-origin' // 携带cookie避免CSRF校验失败 }; return fetch(url, requestOptions).then(handleResponse); }
3. 控制器无需额外调整
你现有的强参数配置已经符合要求,Rails ActiveStorage会自动处理FormData传过来的文件,绑定到mediadata字段完成存储。
内容的提问来源于stack exchange,提问作者mukesh mahara
相关产品推荐
相关产品推荐

