Last active
July 8, 2016 13:23
-
-
Save wudi/e672d3181cb6db98d7b40d56624c8a31 to your computer and use it in GitHub Desktop.
concurrent_download
This file contains hidden or 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
package main | |
import ( | |
"fmt" | |
"io" | |
"io/ioutil" | |
"net/http" | |
"os" | |
"time" | |
) | |
type receiver struct { | |
seqId int | |
buf io.ReadCloser | |
} | |
func main() { | |
fileSize := 10485760 | |
size := 512000 // 500K | |
fileUrl := "http://cdntest-10048632.cos.myqcloud.com/10M.bin" | |
maxTimes := 0 | |
if n := fileSize % size; n == 0 { | |
maxTimes = int(fileSize / size) | |
} else { | |
maxTimes = int(fileSize/size) + 1 | |
} | |
fmt.Printf("File: %s\n", fileUrl) | |
startTime := time.Now() | |
ch := make(chan receiver) | |
for i := 0; i < maxTimes; i++ { | |
go download(fileUrl, i, i*size, i*size+size, ch) | |
} | |
// tmp file | |
tmpFiles := make([]string, maxTimes) | |
// 等待所有任务完成 | |
for i := 0; i < maxTimes; i++ { | |
r := <-ch | |
contents, err := ioutil.ReadAll(r.buf) | |
r.buf.Close() | |
if err != nil { | |
panic(err) | |
} | |
tmpFiles[r.seqId] = fmt.Sprintf("/tmp/download/%d.tmp", r.seqId) | |
ioutil.WriteFile(tmpFiles[r.seqId], contents, 0666) | |
if err != nil { | |
panic(err) | |
} | |
} | |
fmt.Println("Merge tmp files...\n") | |
// 合并文件 | |
file, err := os.OpenFile("./file.tmp", os.O_WRONLY|os.O_CREATE, 0666) | |
if err != nil { | |
panic(err) | |
} | |
for _, f := range tmpFiles { | |
//fmt.Println(f) | |
if b, err := ioutil.ReadFile(f); err != nil { | |
panic(err) | |
break | |
} else { | |
if _, err := file.Write(b); err != nil { | |
panic(err) | |
} | |
} | |
//os.Remove(f) | |
} | |
latency := time.Now().Sub(startTime) | |
fmt.Printf("Download done! \nLatency:%13v\n", latency) | |
} | |
func download(urlStr string, seqId int, rangeFrom int, rangeTo int, ch chan receiver) { | |
request, _ := http.NewRequest(http.MethodGet, urlStr, nil) | |
request.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", rangeFrom, rangeTo)) | |
client := &http.Client{} | |
if response, err := client.Do(request); err != nil { | |
panic(fmt.Sprintf("#%d Error: %s", seqId, err.Error())) | |
} else { | |
if response.StatusCode != http.StatusPartialContent { | |
panic(fmt.Sprintf("#%d Response status invalid", seqId)) | |
} | |
fmt.Printf("#%d\tFinished Range: %d-%d\n", seqId, rangeFrom, rangeTo) | |
ch <- receiver{ | |
seqId: seqId, | |
buf: response.Body, | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment