130 lines
2.6 KiB
Go
130 lines
2.6 KiB
Go
/**
|
|
* Created by IntelliJ IDEA.
|
|
* User: Ar.M
|
|
* Date: 2020-05-10
|
|
* Time: 22:10
|
|
*/
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"github.com/dustin/go-humanize"
|
|
"google.golang.org/grpc"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
transportpb "yunlian-file-transfer-demo/proto"
|
|
)
|
|
|
|
var (
|
|
fn *string
|
|
ip *string
|
|
port *int
|
|
savePath *string
|
|
)
|
|
|
|
func init() {
|
|
fn = flag.String("fn", "", "文件名称")
|
|
ip = flag.String("ip", "127.0.0.1", "服务端 IP 地址")
|
|
port = flag.Int("port", 10086, "服务端端口号")
|
|
savePath = flag.String("savepath", "./", "存储路径")
|
|
|
|
flag.Usage = func() {
|
|
fmt.Println("yunlian-file-transfer-demo version: 0.0.1")
|
|
flag.PrintDefaults()
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
if len(*fn) < 1 {
|
|
flag.Usage()
|
|
return
|
|
}
|
|
|
|
requestedFile := *fn
|
|
serverIp := fmt.Sprintf("%s:%d", *ip, *port)
|
|
|
|
cc, err := grpc.Dial(serverIp, grpc.WithInsecure())
|
|
if err != nil {
|
|
log.Fatalf("监听服务端异常 : %v\n", err)
|
|
}
|
|
defer cc.Close()
|
|
|
|
c := transportpb.NewFileServiceClient(cc)
|
|
|
|
if err := download(requestedFile, c); err != nil {
|
|
log.Fatalf("下载异常 %s : %v\n", requestedFile, err)
|
|
}
|
|
fmt.Printf("\n%s 下载成功\n", requestedFile)
|
|
}
|
|
|
|
func writeFile(fileName string, content []byte) {
|
|
if len(content) != 0 {
|
|
fp, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0755)
|
|
if err != nil {
|
|
log.Fatalf("文件打开异常: %s\n", err)
|
|
}
|
|
defer fp.Close()
|
|
_, err = fp.Write(content)
|
|
if err != nil {
|
|
log.Fatalf("文件保存异常: %s\n", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func getFileStat(fileName string) int64 {
|
|
fileinfo, err := os.Stat(fileName)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return int64(0)
|
|
}
|
|
log.Fatalf("获取文件元数据失败: %s\n", err)
|
|
}
|
|
return fileinfo.Size()
|
|
}
|
|
|
|
func download(fileName string, client transportpb.FileServiceClient) error {
|
|
fileRange := getFileStat(fileName)
|
|
req := &transportpb.FileRequest{
|
|
FileName: fileName,
|
|
FileRange: fileRange,
|
|
}
|
|
|
|
stream, err := client.Download(context.Background(), req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var recvSize int64
|
|
var buffer bytes.Buffer
|
|
|
|
recvSize = fileRange
|
|
for {
|
|
res, err := stream.Recv()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
buffer.Reset()
|
|
return err
|
|
}
|
|
|
|
block := res.GetBlock()
|
|
fileSize := res.GetFileSize()
|
|
blockSize := len(block)
|
|
recvSize += int64(blockSize)
|
|
|
|
writeFile(fileName, block)
|
|
|
|
// fmt.Printf("\r%s", strings.Repeat(" ", 30))
|
|
fmt.Printf("\r文件%s: %s / %s 已下载%s", fileName, humanize.IBytes(uint64(recvSize)), humanize.IBytes(uint64(fileSize)), strings.Repeat(" ", 60))
|
|
}
|
|
return nil
|
|
}
|