最近平台在对接一个三方的安全检测,我们把这套检测的逻辑集成到了平台里,即用户只需要在平台上传对应的文件以后,即会将该文件提交到第三方的平台,但该平台提交文件的接口是需要文件的一个下载链接以及md5值, 所以我们原有的逻辑是将文件提交到三方的cdn平台 如(七牛), 再通过返回的下载链接给到后端做存储,但是md5的逻辑就需要后端通过下载链接将文件下载后计算出md5值才行。
以上的描述就有一个比较严重的问题,即前端已经将文件进行了上传了,但是到了后端以后,仍然需要对文件下载。这个就将流程变的复杂了其中增加了很多的不确定行了。对应大文件下载的耗时也是很难受的,所以得想着怎么在前端去计算md5的值的逻辑。(当然也有同学说完全可以文件直接给后天,由后台直接计算MD5不就可以了吗,这个确实是个方式,只是我们这边文件上传之前前端的通用逻辑都是直接对接到三方的cdn)。 尝试百度了下,找到了解决方案。
由于前端用的antd的Upload组件,所以我们可以在 beforeUpload
中去获取文件的md5值,‘
// 获取文件的md5值
const getFileMd5 = (file) => {
return new Promise((resolve) => {
var tmp_md5;
var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
// file = this.files[0],
chunkSize = 8097152, // Read in chunks of 2MB
chunks = Math.ceil(file.size / chunkSize),
currentChunk = 0,
spark = new SparkMD5.ArrayBuffer(),
fileReader = new FileReader();
fileReader.onload = function (e) {
spark.append(e.target.result); // Append array buffer
currentChunk++;
var md5_progress = Math.floor((currentChunk / chunks) * 100);
console.log(file.name + " 正在处理,请稍等," + "已完成" + md5_progress + "%");
if (currentChunk < chunks) {
loadNext();
} else {
tmp_md5 = spark.end();
console.log(file.name + "的MD5值是:" + tmp_md5)
resolve(tmp_md5);
}
};
fileReader.onerror = function () {
console.warn('oops, something went wrong.');
};
function loadNext() {
var start = currentChunk * chunkSize,
end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
}
loadNext();
})
}
const beforeUpload = async (file) => {
// 这里是为了计算文件的md5值并且做回传, 如果没有则不需要计算
if (props.onFileMd5CalComplete) {
let md5 = await getFileMd5(file);
props.onFileMd5CalComplete(md5);
}
return isLt100M
}
虽然文件的md5值已经获取到了,但是我们的数据提交是一个表单的方式。所以我们还需要将md5值也提交到表单中去,所以我们需要额外有一个隐藏的文本框来进行接收这个值
// 父组件接受方法的回调做的赋值
const onFileMd5CalComplete = (md5:string) => {
setFieldsValue({
'cardInfo.md5': md5
})
}
// ****
// 文本框做md5值,但是文本框做隐藏处理
<FormItem>
{getFieldDecorator('cardInfo.md5', {
initialValue: props.cardDetail.cardInfo.md5,
})(
<Input
style={{visibility: "hidden"}}
/>
)}
</FormItem>
// ****
如此即可在前端将文本的下载链接以及文件的md5值直接给到后端,而不需要后端做下载的处理了。