- 运行目录定位、路径存在性、带进度回调下载、Zip 打包/解压(兼容 GBK 中文文件名) - 附单元测试、examples/filex 例程与包 README
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package filex
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"crypto/tls"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
)
|
|
|
|
// DownloadFile 下载文件到指定路径
|
|
// fb 为进度回调,参数为总长度与已下载长度
|
|
func DownloadFile(url string, downPath string, fb func(length, downLen int64)) error {
|
|
var (
|
|
fileSize int64
|
|
buf = make([]byte, 32*1024)
|
|
written int64
|
|
)
|
|
req, err := http.NewRequest("GET", url, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
//req.Header.Add("Authorization", "BNbmgAAGI155F6MJ3N2Tk9ruL_6XQpx-uxkkg:tGCY3xCsgybHd5IjcDMi9yZXBvcy93aF9mbG93RGF0YVNvdXJjZTEiLCJleHBpcmVzIjoxNTM2NzU4NjQ3LCJjb250ZW5VudFR5cGUiOiIiLCJoZWFkZXJzIjoiIiwibWV0aG9kIjoiR0VUIn0=")
|
|
req.Header.Add("Accept-Encoding", "gzip")
|
|
//req.Header.Set("Content-Encoding", "gzip")
|
|
//req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)")
|
|
req.Header.Set("Accept", " */*")
|
|
// req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
|
|
tr := &http.Transport{
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
}
|
|
client := &http.Client{Transport: tr}
|
|
client.Timeout = time.Second * 300
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
return errors.New(resp.Status)
|
|
}
|
|
|
|
//读取服务器返回的文件大小
|
|
fileSize = resp.ContentLength
|
|
//fmt.Println(resp.Header)
|
|
if fileSize == -1 {
|
|
fmt.Println("取文件长度失败", url)
|
|
}
|
|
|
|
folderPath := filepath.Dir(downPath)
|
|
err = os.MkdirAll(folderPath, os.ModePerm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
//创建文件
|
|
file, err := os.Create(downPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
if resp.Body == nil {
|
|
return errors.New("body is null")
|
|
}
|
|
defer resp.Body.Close()
|
|
//下面是 io.copyBuffer() 的简化版本
|
|
body := resp.Body
|
|
if resp.Header.Get("Content-Encoding") == "gzip" {
|
|
body, err = gzip.NewReader(resp.Body)
|
|
if err != nil {
|
|
fmt.Println("http resp unzip is failed,err: ", err)
|
|
}
|
|
}
|
|
|
|
for {
|
|
//读取bytes
|
|
nr, er := body.Read(buf)
|
|
if nr > 0 {
|
|
//写入bytes
|
|
nw, ew := file.Write(buf[0:nr])
|
|
//数据长度大于0
|
|
if nw > 0 {
|
|
written += int64(nw)
|
|
}
|
|
//写入出错
|
|
if ew != nil {
|
|
err = ew
|
|
break
|
|
}
|
|
//读取是数据长度不等于写入的数据长度
|
|
if nr != nw {
|
|
err = io.ErrShortWrite
|
|
break
|
|
}
|
|
}
|
|
if er != nil {
|
|
if er != io.EOF {
|
|
err = er
|
|
}
|
|
break
|
|
}
|
|
//没有错误了快使用 callback
|
|
fb(fileSize, written)
|
|
}
|
|
return err
|
|
}
|