今天小編給大家分享一下Golang如何實(shí)現(xiàn)文件傳輸功能的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
成都創(chuàng)新互聯(lián)公司長期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為河?xùn)|企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì),河?xùn)|網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
借助TCP完成文件的傳輸,基本思路如下:
1、發(fā)送方(客戶端)向服務(wù)端發(fā)送文件名,服務(wù)端保存該文件名。
2、接收方(服務(wù)端)向客戶端返回一個(gè)消息ok,確認(rèn)文件名保存成功。
3、發(fā)送方(客戶端)收到消息后,開始向服務(wù)端發(fā)送文件數(shù)據(jù)。
4、接收方(服務(wù)端)讀取文件內(nèi)容,寫入到之前保存好的文件中。
首先獲取文件名。借助os包中的stat()函數(shù)來獲取文件屬性信息。在函數(shù)返回的文件屬性中包含文件名和文件大小。Stat參數(shù)name傳入的是文件訪問的絕對路徑。FileInfo中的Name()函數(shù)可以將文件名單獨(dú)提取出來。
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)絡(luò)接收端。 讀多少,寫多少。原封不動。
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)絡(luò)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
}
// 讀取服務(wù)器回發(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]) {
// 寫文件內(nèi)容給服務(wù)器——借助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)絡(luò)中讀數(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"))
// 獲取文件內(nèi)容
recvFile(conn, fileName)
}
以上就是“Golang如何實(shí)現(xiàn)文件傳輸功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。