4.10. 读取 File
Github: github.com/bigfile/bigfile
读取 File
读取 File
也即下载文件,稍微复杂,服务端流式响应,示例如下:
package main
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"io/ioutil"
"strconv"
"github.com/bigfile/bigfile/internal/util"
"github.com/bigfile/bigfile/rpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func createConnection() (*grpc.ClientConn, error) {
var (
err error
conn *grpc.ClientConn
cert tls.Certificate
certPool *x509.CertPool
rootCertBytes []byte
)
// 加载客户端证书
if cert, err = tls.LoadX509KeyPair("client.pem", "client.key"); err != nil {
return nil, err
}
// 创建证书池
certPool = x509.NewCertPool()
if rootCertBytes, err = ioutil.ReadFile("ca.pem"); err != nil {
return nil, err
}
if !certPool.AppendCertsFromPEM(rootCertBytes) {
return nil, err
}
// 连接服务器
if conn, err = grpc.Dial("192.168.0.103:10986", grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: certPool,
}))); err != nil {
return nil, err
}
return conn, err
}
func main() {
var (
err error
conn *grpc.ClientConn
)
if conn, err = createConnection(); err != nil {
fmt.Println(err)
return
}
defer conn.Close()
var (
client = rpc.NewFileReadClient(conn)
header metadata.MD
fileName string
fileHash string
dataHash string
dataBuffer *bytes.Buffer
fileSize int
streamClient rpc.FileRead_FileReadClient
)
// 创建流式客户端
if streamClient, err = client.FileRead(context.Background(), &rpc.FileReadRequest{
Token: "ee3caab522b1848744c9df3aa980346f",
FileUid: "b58a51fc0ee8d95918c9715bfdb2af0d",
}); err != nil {
fmt.Println(err)
return
}
// 读取 Header,Header 存在文件大小, hash 值以及名称
if header, err = streamClient.Header(); err != nil {
fmt.Println(err)
return
}
fileName = header.Get("name")[0]
fileHash = header.Get("hash")[0]
if fileSize, err = strconv.Atoi(header.Get("size")[0]); err != nil {
fmt.Println(err)
return
}
fmt.Printf("name = %s, hash = %s, size = %d\n", fileName, fileHash, fileSize)
dataBuffer = new(bytes.Buffer)
// 持续读取文件
for {
if resp, err := streamClient.Recv(); err != nil {
if err != io.EOF {
fmt.Println(err)
return
}
break
} else {
if _, err = dataBuffer.Write(resp.Content); err != nil {
fmt.Println(err)
return
}
}
}
// 验证 hash
if dataHash, err = util.Sha256Hash2String(dataBuffer.Bytes()); err != nil {
fmt.Println(err)
return
}
if dataHash != fileHash {
fmt.Println("file is broken")
return
}
// 这里,您可以将内容保存到文件
// _ = ioutil.WriteFile(fileName, dataBuffer.Bytes(), 0666)
}
这里我们也给出了下载文件的 示例,点击查看 FileReadRequest 以及 FileReadResponse 类型声明。
英文文档:bigfile.site
推荐文章: