feat(filex): 自 go-hua/common 迁入文件目录工具并独立成包
- 运行目录定位、路径存在性、带进度回调下载、Zip 打包/解压(兼容 GBK 中文文件名) - 附单元测试、examples/filex 例程与包 README
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user