Golang 模拟客户端发送下载请求
最近遇到一个需求,需要本地应用模拟浏览器向服务器端发送下载请求。在google与百度上转了一大圈都没找到。于是自己写了一个,分享出来希望能帮到可以帮的人。程序是基于beego写的。文件的MD5是放在Header中的。当然你也可以根据自己的需求将其放在cookie中或是其他
下面上代码
type DownParameter struct {
DownUrl string
Pid string
FileType string
SavePath string
}
func Downloading(down *DownParameter) error {
// 请求上端获取数据
req := httplib.Post(down.DownUrl)
req.Param("pid", down.Pid)
req.Param("file_type", down.FileType)
resp, err := req.Response()
// 解析上端响应
if err != nil {
logs.Error("Request Downloading File Error : ", err.Error())
return err
}
if resp.StatusCode != http.StatusOK {
logs.Error("Request Downloading File Error : response code is ", resp.StatusCode)
return errors.New(fmt.Sprintf("Request Downloading File Error : response code is %d", resp.StatusCode))
}
md5_code := resp.Header.Get("md5_code")
_, err = os.Stat(common.GetDir(down.SavePath))
if err != nil {
if !os.IsNotExist(err) {
logs.Error("Downloading Error : ", err.Error())
return err
}
err = os.MkdirAll(common.GetDir(down.SavePath), os.ModePerm)
if err != nil {
logs.Error("Downloading Error : ", err.Error())
return err
}
}
// 解析上端响应保存到本地
file, err := os.OpenFile(down.SavePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
if err != nil {
logs.Error("Downloading Error : ", err.Error())
return err
}
_, err = io.Copy(file, resp.Body)
defer resp.Body.Close()
if err != nil {
logs.Error("Downloading Error : ", err.Error())
return err
}
// 获取下载文件的MD5校验码
md5Value, err := common.GetFileMd5(file)
if err != nil {
return err
}
// 验证下载文件与上端服务器传送过来的MD5值是否一致
if md5Value == md5_code {
logs.Error("Downloading Error : Downloading file MD5 inspection failure")
return errors.New("Downloading Error : Downloading file MD5 inspection failure")
}
return nil
}
以下是当中用到的工具函数
/**
功能:获取文件的MD5
*/
func GetFileMd5(file *os.File) (string, error) {
md5 := md5.New()
r := bufio.NewReader(file)
_, err := io.Copy(md5, r)
if err != nil {
logs.Error("Calculate MD5 Error : ", err.Error())
return "", err
}
return fmt.Sprintf("%X", md5.Sum(nil)), nil
}
// 获取文件夹路径
func GetDir(path string) string {
len := strings.Count(path, "/")
if len <= 1 {
if len = strings.Count(path, "."); len <= 0 {
return path
} else {
return ""
}
}
index := strings.LastIndex(path, "/")
dir := path[:index]
fileName := path[index:]
if do := strings.Count(fileName, "."); do <= 0 {
return path
}
return dir
}
// 获取文件名
func GetFileName(path string) string {
if len := strings.Count(path, "/"); len >= 1 {
return path[strings.LastIndex(path, "/"):]
}
return path
}
如果各位在我的代码中看到有不妥的地方,欢迎指正。有更好的实现方式也可以与我一起交流,互相学习~