JS实现1MB以内文件上传验证遇异常:表单仍传大文件返回500
问题分析
你遇到的问题核心有两个:
- 表单默认提交未被阻止:你通过XHR发送了过滤后的FormData,但函数最后返回了
true,导致浏览器同时执行了XHR请求和表单的默认提交操作,默认提交会带上所有选中的文件(包括超过1MB的大文件),这就是大文件仍被上传的原因。 - 缺少CSRF验证:Laravel路由默认需要CSRF令牌验证,你的XHR请求没有携带令牌,这会导致后端返回500错误。
修复后的代码
<form enctype="multipart/form-data" method="post" action="{{route('addFiles.post')}}" onsubmit="return checkFileSizes();"> <!-- 添加Laravel CSRF令牌 --> @csrf <input type="file" name="fileToUpload" id="fileToUpload" multiple> <input type="submit" value="Upload Files" name="submit"> </form> <script> function checkFileSizes() { var fileInput = document.getElementById('fileToUpload'); if (fileInput.files.length === 0) { alert('请选择要上传的文件'); return false; } var validFiles = []; var invalidFiles = []; const maxSize = 1048576; // 1MB // 筛选文件并区分有效/无效 for (var i = 0; i < fileInput.files.length; i++) { const file = fileInput.files[i]; if (file.size <= maxSize) { validFiles.push(file); } else { invalidFiles.push(file.name); } } // 提示被过滤的文件 if (invalidFiles.length > 0) { alert(`以下文件超过1MB限制,已被过滤:\n${invalidFiles.join('\n')}`); } if (validFiles.length === 0) { alert('没有符合大小要求的文件'); return false; } // 创建新的FormData并添加有效文件 var formData = new FormData(); // 携带CSRF令牌 formData.append('_token', document.querySelector('input[name="_token"]').value); for (var j = 0; j < validFiles.length; j++) { // 保持和后端接收字段一致,这里用原字段名fileToUpload[] formData.append('fileToUpload[]', validFiles[j]); } // 发送XHR请求 var xhr = new XMLHttpRequest(); xhr.open('POST', "{{route('addFiles.post')}}", true); // 监听请求结果 xhr.onload = function() { if (xhr.status === 200) { alert('文件上传成功'); // 重置文件输入框 fileInput.value = ''; } else { alert('文件上传失败,请重试'); } }; xhr.send(formData); // 必须返回false阻止表单默认提交 return false; } </script>
关键修改点
- 阻止默认提交:在函数最后返回
false,彻底取消浏览器的默认表单提交行为,只保留XHR的请求。 - 添加CSRF令牌:通过FormData携带Laravel的CSRF令牌,解决500错误。
- 文件筛选反馈:增加对无效文件的提示,提升用户体验。
- 字段名一致:前端
append的字段名fileToUpload[]和原表单输入框的name保持一致,确保后端能正确接收。
后端注意事项
确保你的Laravel控制器处理方法中,接收的字段名是fileToUpload(因为前端用的是fileToUpload[],后端可以用$request->file('fileToUpload')获取文件数组)。
内容的提问来源于stack exchange,提问作者Tejash Vaishnav
相关产品推荐
相关产品推荐

