Canvas.toDataURL转PHP base64解码乱码,如何适配WP文件上传逻辑?
问题:Canvas生成的Base64图片字符串转存适配原有PHP上传逻辑失败
问题背景
我尝试把Canvas通过canvas.toDataURL('image/png')生成的Base64图片字符串,用AJAX发送到PHP后解码保存到文件夹。生成的字符串格式如下:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXYAAAF1CAYAAAD8ysHLAAAgAElEQVR4XuydCbiOVff/lw...
字符串长度约43000字符,按网上方案解码后得到“乱码”内容,没法适配之前正常运行的文件上传逻辑。
当前代码
AJAX请求代码
form_data = new FormData(); form_data.append('file', newImage); form_data.append('action', 'file_upload'); form_data.append('security', blog.security); // 发送AJAX请求 $.ajax({ url: blog.ajaxurl, type: 'POST', contentType: false, processData: false, data: form_data, ...
PHP解码代码
$img64String = $_POST['file']; $img64String = str_replace('data:image/png;base64,', '', $img64String); $img64String = str_replace(' ', '+', $img64String); $fileData = base64_decode($img64String);
解码后内容示例(所谓“乱码”)
FileData: �PNG IHDRvu���� IDATx^� ��U���eʔ! ! %��Pр$C*�FC��FD��&�(RRƷdJ�䯼Pʔyʐ�����?�s�9g�������ֺ.W�s�}��| ��߽�����8�?&fF�#�@��5si�#�dka�����f�i�? ���d�1'ݔ'�#�k���Ʉ]7��V&�...
原有正常运行的PHP上传逻辑
$file_type = $_FILES['file']['type']; $file_name = $_FILES['file']['name']; $file_temp_name = $_FILES['file']['tmp_name']; $allowed_file_types = array('image/png', 'image/jpeg', 'image/jpg'); if (in_array($file_type, $allowed_file_types)) { $upload = wp_upload_bits($file_name, null, file_get_contents($file_temp_name)); $status = "ok"; }
问题分析与解决方案
- “乱码”是正常现象:你看到的乱码是PNG图片的二进制原始内容,说明Base64解码已经成功了,不是解码失败。
- 适配原有逻辑的核心问题:原有代码依赖
$_FILES数组,但你现在是通过$_POST传递Base64字符串,不需要硬套$_FILES的逻辑,直接把解码后的二进制数据传给wp_upload_bits即可。
修正后的PHP代码
// 获取前端传来的Base64字符串 $img64String = $_POST['file']; // 剥离Base64前缀(兼容png/jpg/jpeg) $img64String = preg_replace('/^data:image\/(png|jpeg|jpg);base64,/', '', $img64String); // 替换空格为+(处理URL编码可能导致的字符转换) $img64String = str_replace(' ', '+', $img64String); // 解码得到图片二进制数据 $fileData = base64_decode($img64String); // 提取图片类型并生成文件名 preg_match('/^data:image\/(png|jpeg|jpg);base64,/', $_POST['file'], $matches); $file_type = 'image/' . $matches[1]; $file_ext = $matches[1]; $file_name = 'canvas_upload_' . time() . '.' . $file_ext; // 用时间戳避免文件名重复 // 复用原有验证逻辑 $allowed_file_types = array('image/png', 'image/jpeg', 'image/jpg'); if (in_array($file_type, $allowed_file_types) && $fileData !== false) { // 直接传递二进制数据给wp_upload_bits,不需要临时文件 $upload = wp_upload_bits($file_name, null, $fileData); $status = "ok"; } else { $status = "error"; }
关键优化说明
- 动态提取图片类型,避免硬编码,适配多种图片格式;
- 增加
$fileData !== false判断,过滤Base64解码失败的无效数据; - 用时间戳生成文件名,避免重复覆盖问题。
内容的提问来源于stack exchange,提问作者eligolf
相关产品推荐
相关产品推荐

