Created
October 18, 2015 09:10
-
-
Save XUJiahua/27fc59647298cf59edbc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
理论基础: https://en.wikipedia.org/wiki/Byte_serving | |
使用range header可以得到网络资源的一部分字节 | |
*/ | |
package main | |
import ( | |
"net/http" | |
"fmt" | |
"os" | |
"io/ioutil" | |
"strconv" | |
) | |
func myPanic(err error) { | |
fmt.Printf("%s\n", err) | |
os.Exit(1) | |
} | |
const url = "http://download.cardinfolink.net/android/showmoney.apk" | |
const threadNum = 3 | |
func getPartOfFile(start, end int) ([]byte, error) { | |
client := &http.Client{} | |
req, err := http.NewRequest("GET", url, nil) | |
if err != nil { | |
return nil, err | |
} | |
rangeVal := fmt.Sprintf("bytes=%d-%d", start, end) | |
req.Header.Set("Range", rangeVal) | |
response, err := client.Do(req) | |
if err != nil { | |
return nil, err | |
} | |
defer response.Body.Close() | |
contents, err := ioutil.ReadAll(response.Body) | |
if err != nil { | |
return nil, err | |
} | |
fmt.Println("getPartOfFile done") | |
c <- FilePiece{start:start, end:end, contents:contents} | |
return contents, nil | |
} | |
type FilePiece struct { | |
start, end int | |
contents []byte | |
} | |
const filename = "/Users/jiahua/Downloads/xxx.apk" | |
var c = make(chan FilePiece, threadNum) | |
func main() { | |
res, err := http.Head(url) | |
if err != nil { | |
myPanic(err) | |
} | |
fileLen, err := strconv.Atoi(res.Header.Get("Content-Length")) | |
if err != nil { | |
myPanic(err) | |
} | |
blockSize := fileLen / threadNum | |
remainingSize := fileLen % threadNum | |
fmt.Printf("fileSize: %d, blockSize for each thread: %d, remainingSize: %d\n", fileLen, blockSize, remainingSize) | |
for i := 0; i < threadNum; i++ { | |
start := i * blockSize | |
end := (i + 1) * blockSize - 1 | |
if threadNum - 1 == i { | |
end += remainingSize | |
} | |
fmt.Printf("Thread%d, start: %d end: %d\n", i, start, end) | |
go getPartOfFile(start, end) | |
} | |
file, err := os.Create(filename) | |
if err != nil { | |
myPanic(err) | |
} | |
defer file.Close() | |
for i := 0; i < threadNum; i++ { | |
//routine返回的结果 | |
fp := <-c | |
fmt.Printf("Content received, start: %d end: %d\n", fp.start, fp.end) | |
// WriteAt会overwrite原有数据,之前一段不存在也能写入.. | |
_, err := file.WriteAt(fp.contents, int64(fp.start)) | |
if err != nil { | |
myPanic(err) | |
} | |
} | |
file.Sync() | |
fmt.Println("File download Done") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment