Golang實現(xiàn)Md5校驗的示例代碼
最近項目中有個需求,就是地圖文件下發(fā)后,接收方需要文件的md5值,和接收到的文件做比對,以免文件不完整,引起bug,于是測試了下本地文件和遠(yuǎn)程文件的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()
// 創(chuàng)建一個md5哈希對象
hasher := md5.New()
// 將文件內(nèi)容讀入哈希對象
if _, err := io.Copy(hasher, file); err != nil {
fmt.Println("Failed to read file:", err)
return
}
// 計算并獲取哈希值
hashBytes := hasher.Sum(nil)
// 將哈希值轉(zhuǎn)換為十六進(jìn)制字符串
hashString := hex.EncodeToString(hashBytes)
// 輸出MD5哈希值
fmt.Println("MD5 hash of the file:", hashString)
}
輸出結(jié)果如下:
PS D:\gostudy2022\TimeScheduler\md5> go run .\main.go
LocalFile MD5 hash of the file: b4735b024f3552b1277671303149719b
2、遠(yuǎn)程文件
遠(yuǎn)程文件其實就是網(wǎng)絡(luò)中可訪問的資源文件,要獲取指定網(wǎng)絡(luò)地址的文件的MD5值,你需要先下載文件的內(nèi)容到內(nèi)存或磁盤上,然后再計算其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"
// 發(fā)起HTTP GET請求
resp, err := http.Get(url)
if err != nil {
fmt.Println("Failed to fetch file:", err)
return
}
defer resp.Body.Close()
// 檢查響應(yīng)狀態(tài)碼
if resp.StatusCode != http.StatusOK {
fmt.Printf("Failed to fetch file: HTTP status code %d\n", resp.StatusCode)
return
}
// 創(chuàng)建一個md5哈希對象
hasher := md5.New()
// 將文件內(nèi)容讀入哈希對象
if _, err := io.Copy(hasher, resp.Body); err != nil {
fmt.Println("Failed to read file:", err)
return
}
// 計算并獲取哈希值
hashBytes := hasher.Sum(nil)
// 將哈希值轉(zhuǎn)換為十六進(jìn)制字符串
hashString := hex.EncodeToString(hashBytes)
// 輸出MD5哈希值
fmt.Println("MD5 hash of the file:", hashString)
}
這里遠(yuǎn)程文件和上例的文件相同,輸出結(jié)果如下:
PS D:\gostudy2022\TimeScheduler\md5> go run .\main.go
RemoteFile MD5 hash of the file: b4735b024f3552b1277671303149719b
可以看到,本地文件和遠(yuǎn)程文件的md5值是相同的,從而在項目中,我們可以根據(jù)md5值是否相同,判斷文件是不是同一個文件,有沒有被損壞或篡改。
補(bǔ):golang 分片上傳md5校驗不一致問題
錯誤計算md5值
// 打開合成文件
complateFile, _ := os.Create("./test.zip")
defer complateFile.Close()
// 循環(huán)分片合成
for i := 0; i < 5; i++ {
// ... 省略中間步驟
complateFile.Write(fileBuffer)
}
// 計算分片md5進(jìn)行比對
m5 := md5.New()
_, _ = io.Copy(m5, complateFile)
complateFileMd5 := hex.EncodeToString(m5.Sum(nil))
if complateFileMd5 != originalFileMd5{
fmt.Println("md5驗證失敗")
}
錯誤原因
在Go中,如果你在合并分片文件的過程中直接使用*os.File(即file指針)來計算MD5,這通常會導(dǎo)致計算錯誤,原因在于文件指針的位置。當(dāng)你打開一個文件并開始讀取時,文件指針默認(rèn)位于文件的開頭。如果你在合并過程中不重置文件指針,每次讀取都會從上次停止的地方開始,而不是從頭開始,導(dǎo)致計算的MD5不正確。
解決方案
- 計算md5前重置文件指針到文件的開頭
complateFile.Seek(0,0)
- 合成文件后重新打開文件進(jìn)行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驗證失敗")
}到此這篇關(guān)于Golang實現(xiàn)Md5校驗的示例代碼的文章就介紹到這了,更多相關(guān)Golang Md5校驗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言學(xué)習(xí)之?dāng)?shù)組的用法詳解
數(shù)組是相同數(shù)據(jù)類型的一組數(shù)據(jù)的集合,數(shù)組一旦定義長度不能修改,數(shù)組可以通過下標(biāo)(或者叫索引)來訪問元素。本文將通過示例詳細(xì)講解Go語言中數(shù)組的使用,需要的可以參考一下2022-04-04
GOLANG使用Context管理關(guān)聯(lián)goroutine的方法
這篇文章主要介紹了GOLANG使用Context管理關(guān)聯(lián)goroutine的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01
Golang源碼分析之golang/sync之singleflight
golang/sync庫拓展了官方自帶的sync庫,提供了errgroup、semaphore、singleflight及syncmap四個包,本次先分析第一個包errgroup的源代碼,下面這篇文章主要給大家介紹了關(guān)于Golang源碼分析之golang/sync之singleflight的相關(guān)資料,需要的朋友可以參考下2022-11-11
Go使用Gin寫一個對MySQL的增刪改查的實現(xiàn)
本文主要介紹了使用Go語言結(jié)合Gin和GORM框架創(chuàng)建users表,實現(xiàn)增刪查接口,配置mysql依賴并啟動服務(wù)測試數(shù)據(jù)操作,具有一定的參考價值,感興趣的可以了解一下2025-07-07
Go語言結(jié)合gorm實現(xiàn)讀取PostgreSQL的json數(shù)據(jù)類型
使用gorm讀取PostgreSQL中json/jsonb類型數(shù)據(jù)是一個常見的操作,本文介紹幾種方法,適用于幾類不同的場景,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-10-10

