如何在不使用file类型输入的情况下利用PHP的$_FILES变量?
问题
前端通过JavaScript对图片缩放处理后转为base64存入隐藏input,希望通过AJAX提交表单时模拟multipart/form-data格式上传,让后端PHP能通过$_FILES变量识别文件,而非依赖type="file"的输入元素。现有AJAX配置无法实现该需求,后端PHP已编写完成但无法识别上传文件。
相关代码如下:
前端JS代码
$("#base_img_to_compress").on("change", (e) => { resizeImage(source, 1440, 1080).then((imgData) => { appendToFormHiddenImageInput("base_img_data",imgData); }); }); $("#upload_form").on("submit",(e)=>{ $.ajax({ method:"POST", //How I can configure the postdata here ? }) }); function appendToFormHiddenImageInput(name, imgData) { const child = $("#upload_form").children("input[name=" + name + "]"); if (child.length > 0) { child.remove(); } const input = document.createElement('input'); input.type = "hidden"; input.setAttribute("type", "hidden"); input.setAttribute("name", name); input.setAttribute("value", imgData); $("#upload_form").append(input); } function resizeImage(element, width, height) { const element_file = element.files[0]; return imageConversion.compressAccurately(element_file, { quality: 0.7, type: "image/png", width: width, height: height, size: 80 }).then((file) => { return imageConversion.filetoDataURL(file); })
前端HTML代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/WangYuLue/image-conversion/build/conversion.js"></script> <form id="upload_form"> <button type="submit" id="savebtn">Save me</button> </form> <input id="base_img_to_compress" type="file" />
后端PHP代码
$file = $_FILES['base_img_data']; if($file['tmp_name']) { echo "FILE UPLOADED"; exit; } echo "FILE NOT UPLOADED";
解决方案
要让PHP通过$_FILES识别上传文件,必须通过FormData对象模拟原生文件上传的multipart/form-data格式,不能直接提交base64字符串。以下是修改步骤:
1. 调整图片压缩逻辑,保留File对象(而非转base64)
修改resizeImage函数,直接返回压缩后的File对象,避免不必要的base64转换,提升效率:
function resizeImage(element, width, height) { const element_file = element.files[0]; // 直接返回压缩后的File对象,不用转base64 return imageConversion.compressAccurately(element_file, { quality: 0.7, type: "image/png", width: width, height: height, size: 80 }); }
2. 存储压缩后的File对象,而非存入隐藏input
不需要用隐藏input保存base64,直接在全局或闭包中存储File对象:
let compressedFile = null; // 全局存储压缩后的File对象 $("#base_img_to_compress").on("change", (e) => { resizeImage(e.target, 1440, 1080).then((file) => { compressedFile = file; // 保存File对象 }); });
3. 配置AJAX提交FormData
在表单提交事件中,创建FormData并添加File对象,同时设置jQuery AJAX的必要参数:
$("#upload_form").on("submit",(e)=>{ e.preventDefault(); // 阻止表单默认提交行为 if (!compressedFile) { alert("请先选择并压缩图片"); return; } const formData = new FormData(); // 将File对象添加到FormData,参数对应后端$_FILES的键名 formData.append('base_img_data', compressedFile, compressedFile.name); $.ajax({ method: "POST", url: "你的后端接口地址", // 替换为实际的PHP接口路径 data: formData, processData: false, // 禁止jQuery处理FormData,避免转成字符串 contentType: false, // 禁止jQuery设置Content-Type,让浏览器自动生成multipart格式头 success: function(response) { console.log(response); alert(response); }, error: function(xhr) { console.error("上传失败:", xhr); } }); });
4. (可选)如果必须使用base64转File对象
如果因业务需求必须保留base64转存逻辑,可以通过以下代码将base64转为File对象:
function base64ToFile(base64Data, filename, mimeType) { const arr = base64Data.split(','); const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while(n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, {type: mimeType}); } // 使用示例 // const file = base64ToFile(imgData, "compressed.png", "image/png");
修改后,后端PHP的$_FILES['base_img_data']就能正常获取到上传的文件信息,返回"FILE UPLOADED"。
内容的提问来源于stack exchange,提问作者Dimitrios Desyllas
相关产品推荐
相关产品推荐

