在我的客户端中,用户选择要上传的照片,我们使用画布对其进行小型转换,将其大小调整为最大高度/宽度(保留纵横比)2500 像素。用户提交后,服务器将其写入文件并使用
md5_file
以文件 md5 哈希值进行响应。客户端上的 md5 与服务器返回的不匹配,我不知道为什么......
生成 md5 的 JS 库是
crypto-js
,我们使用的是 jquery,因此希望在 html 元素上看到 $
和 jquery 方法。
客户端代码是:
/** This accepts the file from either the file input or a paste event, then resizes it
using the canvas to a max of 2500x2500px while maintaing aspect ratio. The base64 data is
then set at the img src attribute and then an html element is added to the imageContainer */
function handleImage(file, imageContainer) {
const reader = new FileReader();
reader.onload = function(event) {
const img = new Image();
img.src = event.target.result;
img.onload = function() {
const maxDimension = 2500;
let width = img.width;
let height = img.height;
// Resize the image if it exceeds the maximum dimensions
if (width > maxDimension || height > maxDimension) {
if (width > height) {
width = maxDimension;
height = (maxDimension * img.height) / img.width;
} else {
height = maxDimension;
width = (maxDimension * img.width) / img.height;
}
}
// Create a canvas element to draw the resized image
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
// Convert the canvas to a data URL
const resizedDataUrl = canvas.toDataURL(file.type);
const imageType = file.type.split("/")[1];
const imagePreview = $("<div class='image-preview'><div class='loadingIcon' style='display:none'></div><img src='" + resizedDataUrl + "' data-type='" + imageType + "'><span class='remove-image'><i class='far fa-times'></i></span></div>");
imageContainer.append(imagePreview);
imagePreview.find(".remove-image").click(function() {
imagePreview.remove();
});
};
};
reader.readAsDataURL(file);
}
...
/** Called during the submit event, grabs the base64 image data and the filetype, generates an md5 using only the image data, and then sends to the serve. */
function uploadImages(img) {
const imgData = img.attr('src')
const imgHash = CryptoJS.MD5(imgData.replace(/^data:image\/(\w*);base64,/, ""));
const imgType = img.data('type')
$.ajax({
url: 'files',
data: { file: imgData, fileType: imgType},
method: "POST",
dataType: "JSON",
success: function (r) {
container.find('.loadingIcon').hide();
// TODO: These aren't matching, need to figure out why...
console.log(r.md5, imgHash.toString())
}
})
}
服务器代码是:
<?
// this accepts the file data from the $_POST body, strips out the base64 header, and
// then writes the file. Then uses the md5_file function to generate the md5 and
// echos it back.
$file = $_POST['file'];
$fileType = $_POST['fileType'] ?? 'jpg';
$targetPath = "/uploads/files/" . uniqid() . "." . $fileType;;
$data = explode( ',', $file )[1]; // strip out the base64 header
$imageData = base64_decode($data);
file_put_contents($targetPath, $imageData);
echo md5_file($targetPath);
?>
请注意,为了简洁起见,代码已被简化。
但是我在客户端生成的md5与服务器返回的md5不匹配。
有人看到我做错了什么吗?
谢谢!
在 js 中,您仅对 Base64 字符串进行哈希处理,而在 php 中,您对真实文件进行哈希处理。这两件事完全不同,所以这是有道理的。如果你希望它是相同的,你必须在 js 上对缓冲区进行哈希