最近项目中有个需求,就是地图文件下发后,接收方需要文件的md5值,和接收到的文件做比对,以免文件不完整,引起bug,于是测试了下本地文件和远程文件的md5计算。
1、本地文件
要获取指定本地文件的md5值,你可以使用crypto/md5包来计算文件的md5散列值。以下是一个示例代码,演示了如何打开一个文件并计算其md5值:
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"net/http"
"os"
)
func main() {
md5bylocalfile()
}
func md5bylocalfile() {
// // 指定文件路径
filepath := "d:/code/000fa28f-c114-49fe-9699-8c7f8b2eb222.png"
// filepath := "https://minio.dev.inrobot.cloud/map/000fa28f-c114-49fe-9699-8c7f8b2eb222.png"
// 打开文件
file, err := os.open(filepath)
if err != nil {
fmt.println("failed to open file:", err)
return
}
defer file.close()
// 创建一个md5哈希对象
hasher := md5.new()
// 将文件内容读入哈希对象
if _, err := io.copy(hasher, file); err != nil {
fmt.println("failed to read file:", err)
return
}
// 计算并获取哈希值
hashbytes := hasher.sum(nil)
// 将哈希值转换为十六进制字符串
hashstring := hex.encodetostring(hashbytes)
// 输出md5哈希值
fmt.println("md5 hash of the file:", hashstring)
}
输出结果如下:
ps d:\gostudy2022\timescheduler\md5> go run .\main.go
localfile md5 hash of the file: b4735b024f3552b1277671303149719b
2、远程文件
远程文件其实就是网络中可访问的资源文件,要获取指定网络地址的文件的md5值,你需要先下载文件的内容到内存或磁盘上,然后再计算其md5值。这里我展示一个示例,该示例使用net/http包来下载文件,并使用crypto/md5包来计算md5值。以下是完整的示例代码:
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"net/http"
"os"
)
func main() {
md5byremotefile()
}
func md5byremotefile() {
// 指定文件的url
url := "https://minio.dev.inrobot.cloud/map/000fa28f-c114-49fe-9699-8c7f8b2eb222.png"
// 发起http get请求
resp, err := http.get(url)
if err != nil {
fmt.println("failed to fetch file:", err)
return
}
defer resp.body.close()
// 检查响应状态码
if resp.statuscode != http.statusok {
fmt.printf("failed to fetch file: http status code %d\n", resp.statuscode)
return
}
// 创建一个md5哈希对象
hasher := md5.new()
// 将文件内容读入哈希对象
if _, err := io.copy(hasher, resp.body); err != nil {
fmt.println("failed to read file:", err)
return
}
// 计算并获取哈希值
hashbytes := hasher.sum(nil)
// 将哈希值转换为十六进制字符串
hashstring := hex.encodetostring(hashbytes)
// 输出md5哈希值
fmt.println("md5 hash of the file:", hashstring)
}
这里远程文件和上例的文件相同,输出结果如下:
ps d:\gostudy2022\timescheduler\md5> go run .\main.go
remotefile md5 hash of the file: b4735b024f3552b1277671303149719b
可以看到,本地文件和远程文件的md5值是相同的,从而在项目中,我们可以根据md5值是否相同,判断文件是不是同一个文件,有没有被损坏或篡改。
补:golang 分片上传md5校验不一致问题
错误计算md5值
// 打开合成文件
complatefile, _ := os.create("./test.zip")
defer complatefile.close()
// 循环分片合成
for i := 0; i < 5; i++ {
// ... 省略中间步骤
complatefile.write(filebuffer)
}
// 计算分片md5进行比对
m5 := md5.new()
_, _ = io.copy(m5, complatefile)
complatefilemd5 := hex.encodetostring(m5.sum(nil))
if complatefilemd5 != originalfilemd5{
fmt.println("md5验证失败")
}
错误原因
在go中,如果你在合并分片文件的过程中直接使用*os.file(即file指针)来计算md5,这通常会导致计算错误,原因在于文件指针的位置。当你打开一个文件并开始读取时,文件指针默认位于文件的开头。如果你在合并过程中不重置文件指针,每次读取都会从上次停止的地方开始,而不是从头开始,导致计算的md5不正确。
解决方案
- 计算md5前重置文件指针到文件的开头
complatefile.seek(0,0)
- 合成文件后重新打开文件进行md5值计算
func(){
complatefile, _ := os.create("./test.zip")
defer complatefile.close()
for i := 0; i < 5; i++ {
// ... 省略中间步骤
complatefile.write(filebuffer)
}
}()
// 验证文件的完整性
file, _ := os.open("./test.zip")
m5 := md5.new()
_, _ = io.copy(m5, file)
complatefilemd5 := hex.encodetostring(m5.sum(nil))
if complatefilemd5 != originalfilemd5{
fmt.println("md5验证失败")
}到此这篇关于golang实现md5校验的示例代码的文章就介绍到这了,更多相关golang md5校验内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论