php怎么实现多图压缩上传_php前端压缩后传给PHP处理【压缩】

1次阅读

php 的 $_files 为空是因为前端未正确构造 formdata:漏掉 name 字段、未用 file 对象包装 blob、键名不匹配或未以 multipart/form-data 发送。

php怎么实现多图压缩上传_php前端压缩后传给PHP处理【压缩】

前端canvas 压缩图片后传给 PHP,为什么 PHP 里 $_FILES 里没文件?

因为前端压缩后生成的是 BlobFile 对象,但没正确构造 FormData —— 尤其容易漏掉 name 字段,导致 PHP 不识别为上传文件。PHP 的 $_FILES 只认 multipart/form-data 中带 namefile 字段,其他方式(比如直接传 base64 字符串)不会进 $_FILES

实操建议:

  • 前端压缩完图片,用 canvas.toBlob() 转成 Blob,再用 new File([blob], filename, {type: 'image/jpeg'}) 包一层,确保有合法文件名和 MIME 类型
  • FormData.append('images[]', file) —— 注意键名要和 PHP 后端读取的 $_FILES['images'] 一致,加 [] 表示多图
  • 别用 json.stringify() 发送,必须用原生 fetchXMLHttpRequestFormData,且不能手动设 Content-Type(让浏览器自动设 multipart/form-data; boundary=...

PHP 接收多图时 $_FILES['images']['Error'] 全是 UPLOAD_ERR_NO_FILE

这基本等于前端根本没发成功,或者发了但字段名对不上。PHP 不会报错,只是默默把对应字段置为空数组。

排查重点:

立即学习PHP免费学习笔记(深入)”;

  • 打印 var_dump($_FILES) 看结构,确认键名是不是 images,而不是 imagefiles 或带空格/大小写错误
  • 检查前端是否用了 enctype="multipart/form-data"(如果是表单 submit)或是否在 fetch 中漏了 body: formData
  • chrome DevTools → Network → 点开请求 → Headers → 查看 Form Data 面板,确认里面真有文件内容,而不仅是空 key

PHP 用 imagejpeg() 压缩 JPEG 时画质崩了或变黑

常见原因是没正确处理 Alpha 通道(比如 PNG 转 JPEG),或者图像资源创建失败后还强行操作。

安全做法:

  • 先用 getimagesize() 检查文件类型和尺寸,过滤掉非图片或超大文件(如 >20MB)
  • imagecreatefromjpeg()/imagecreatefrompng() 创建资源前,加 @ 抑制警告,并判断返回值是否为 false
  • PNG 转 JPEG 必须手动填充背景色:$bg = imagecolorallocate($img, 255, 255, 255); imagefill($img, 0, 0, $bg);,否则透明区域变黑
  • imagejpeg($img, NULL, 80) 第三个参数控制质量,75–85 是画质/体积平衡点;低于 60 易出现明显色块

并发上传多图时 PHP 写文件失败或覆盖

多个请求同时写同一个临时路径、或用固定文件名(如 upload.jpg)会导致覆盖或权限冲突。

必须做:

  • uniqid('', true) + mt_rand() 生成唯一文件名,例如:$filename = uniqid('img_') . '_' . mt_rand(1000,9999) . '.jpg';
  • 目标目录要提前 mkdir($dir, 0755, true),并确认 PHP 进程有写权限(尤其 nginx+PHP-FPM 场景下,用户常是 www-data
  • 不要直接 move_uploaded_file($_FILES['images']['tmp_name'][$i], $target),要逐个循环处理,每个文件单独校验 $_FILES['images']['error'][$i] === UPLOAD_ERR_OK
  • 上传完成后记得 imagedestroy($img) 释放内存,尤其批量处理时防 OOM

真正麻烦的是前后端时间差:前端压缩耗时不可控,用户可能连点两次提交,后端没做重复请求拦截或幂等处理,就会收到两套同名但不同内容的图。这事得靠前端加 loading 锁 + 后端接收到后生成唯一任务 ID 记日志,不是光靠文件名能兜住的。

text=ZqhQzanResources