Golang實現(xiàn)文件傳輸功能
本文實例為大家分享了Golang實現(xiàn)文件傳輸?shù)木唧w代碼,供大家參考,具體內容如下
借助TCP完成文件的傳輸,基本思路如下:
1、發(fā)送方(客戶端)向服務端發(fā)送文件名,服務端保存該文件名。
2、接收方(服務端)向客戶端返回一個消息ok,確認文件名保存成功。
3、發(fā)送方(客戶端)收到消息后,開始向服務端發(fā)送文件數(shù)據(jù)。
4、接收方(服務端)讀取文件內容,寫入到之前保存好的文件中。
首先獲取文件名。借助os包中的stat()函數(shù)來獲取文件屬性信息。在函數(shù)返回的文件屬性中包含文件名和文件大小。Stat參數(shù)name傳入的是文件訪問的絕對路徑。FileInfo中的Name()函數(shù)可以將文件名單獨提取出來。
func Stat(name string) (FileInfo, error)? type FileInfo interface { ? ?Name() string ? ? ?? ? ?Size() int64 ? ? ? ? ? ?Mode() FileMode ? ?? ? ?ModTime() time.Time? ? ?IsDir() bool ? ? ? ? ? ?Sys() interface{} ?? }
發(fā)送端:
package main import ( ?? ?"fmt" ?? ?"io" ?? ?"net" ?? ?"os" ) func sendFile(conn net.Conn, filePath string) { ?? ?// 只讀打開文件 ?? ?f, err := os.Open(filePath) ?? ?if err != nil { ?? ??? ?fmt.Println("os.Open err:", err) ?? ??? ?return ?? ?} ?? ?defer f.Close() ?? ?// 從本文件中,讀數(shù)據(jù),寫給網(wǎng)絡接收端。 讀多少,寫多少。原封不動。 ?? ?buf := make([]byte, 1024) ?? ?for { ?? ??? ?n, err := f.Read(buf) ?? ??? ?if err != nil { ?? ??? ??? ?if err == io.EOF { ?? ??? ??? ??? ?fmt.Println("發(fā)送文件完成。") ?? ??? ??? ?} else { ?? ??? ??? ??? ?fmt.Println("os.Open err:", err) ?? ??? ??? ?} ?? ??? ??? ?return ?? ??? ?} ?? ??? ?// 寫到網(wǎng)絡socket中 ?? ??? ?_, err = conn.Write(buf[:n]) ?? ??? ?if err != nil { ?? ??? ??? ?fmt.Println("conn.Write err:", err) ?? ??? ??? ?return ?? ??? ?} ?? ?} } func main() { ?? ?list := os.Args // 獲取命令行參數(shù) ?? ?if len(list) != 2 { ?? ??? ?fmt.Println("格式為:go run xxx.go 文件絕對路徑") ?? ??? ?return ?? ?} ?? ?// 提取 文件的絕對路徑 ?? ?filePath := list[1] ?? ?//提取文件名 ?? ?fileInfo, err := os.Stat(filePath) ?? ?if err != nil { ?? ??? ?fmt.Println("os.Stat err:", err) ?? ??? ?return ?? ?} ?? ?fileName := fileInfo.Name() ?? ?// 主動發(fā)起連接請求 ?? ?conn, err := net.Dial("tcp", "127.0.0.1:8000") ?? ?if err != nil { ?? ??? ?fmt.Println("net.Dial err:", err) ?? ??? ?return ?? ?} ?? ?defer conn.Close() ?? ?// 發(fā)送文件名給 接收端 ?? ?_, err = conn.Write([]byte(fileName)) ?? ?if err != nil { ?? ??? ?fmt.Println("conn.Write err:", err) ?? ??? ?return ?? ?} ?? ?// 讀取服務器回發(fā)的 OK ?? ?buf := make([]byte, 1024) ?? ?n, err := conn.Read(buf) ?? ?if err != nil { ?? ??? ?fmt.Println("conn.Read err:", err) ?? ??? ?return ?? ?} ?? ?if "ok" == string(buf[:n]) { ?? ??? ?// 寫文件內容給服務器——借助conn ?? ??? ?sendFile(conn, filePath) ?? ?} }
接收端:
package main import ( ?? ?"fmt" ?? ?"net" ?? ?"os" ) func recvFile(conn net.Conn, fileName string) { ?? ?// 按照文件名創(chuàng)建新文件 ?? ?f, err := os.Create(fileName) ?? ?if err != nil { ?? ??? ?fmt.Println("os.Create err:", err) ?? ??? ?return ?? ?} ?? ?defer f.Close() ?? ?// 從 網(wǎng)絡中讀數(shù)據(jù),寫入本地文件 ?? ?buf := make([]byte, 1024) ?? ?for { ?? ??? ?n, _ := conn.Read(buf) ?? ??? ?if n == 0 { ?? ??? ??? ?fmt.Println("接收文件完成。") ?? ??? ??? ?return ?? ??? ?} ?? ??? ?// 寫入本地文件,讀多少,寫多少。 ?? ??? ?f.Write(buf[:n]) ?? ?} } func main() { ?? ?// 創(chuàng)建用于監(jiān)聽的socket ?? ?listener, err := net.Listen("tcp", "127.0.0.1:8000") ?? ?if err != nil { ?? ??? ?fmt.Println(" net.Listen err:", err) ?? ??? ?return ?? ?} ?? ?defer listener.Close() ?? ?fmt.Println("接收端啟動成功,等待發(fā)送端發(fā)送文件!") ?? ?// 阻塞監(jiān)聽 ?? ?conn, err := listener.Accept() ?? ?if err != nil { ?? ??? ?fmt.Println(" listener.Accept() err:", err) ?? ??? ?return ?? ?} ?? ?defer conn.Close() ?? ?// 獲取文件名,保存 ?? ?buf := make([]byte, 1024) ?? ?n, err := conn.Read(buf) ?? ?if err != nil { ?? ??? ?fmt.Println(" conn.Read err:", err) ?? ??? ?return ?? ?} ?? ?fileName := string(buf[:n]) ?? ?// 回寫 ok 給發(fā)送端 ?? ?conn.Write([]byte("ok")) ?? ?// 獲取文件內容 ?? ?recvFile(conn, fileName) }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Go語言開發(fā)kube-scheduler整體架構深度剖析
這篇文章主要為大家介紹了Go語言開發(fā)kube-scheduler整體架構深度剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04Linux系統(tǒng)下Go語言開發(fā)環(huán)境搭建
這篇文章主要介紹了Linux系統(tǒng)下Go開發(fā)環(huán)境搭建,需要的朋友可以參考下2022-04-04