golang文件上传到服务器,golang文件传输服务

续上篇,本篇介绍一个完整的golang文件传输服务器。

完整的代码可以看服务器,客户端

网络使用的框架如上篇介绍,这里就不再复述.

首先定义3个命令码:

const (

request_file= 1file_size= 2transfering= 3)

request_file用于请求文件传输,附带的命令参数是文件key.

file_size用于通告客户端文件的大小.

transfering用于传输文件内容,附带参数是文件内容的二进制数据.

服务器的文件配置示例

../learnyouhaskell.pdf=haskell

../golang.1.1.2.chm=golang

../NodeJS.pdf=NodeJS

上面的文件配置了3个文件可供传输=左边是文件路径,右边是请求文件时使用的key.

服务器启动时首先调用loadfile将文件导入到内存中,然后根据定义的key,将文件内容插入到字典filemap中:

func loadfile(){//从配置导入文件

F,err := os.Open("./config.txt")if err != nil{

fmt.Printf("config.txt open failed\n")return}

filemap=make(map[string][]byte)

bufferReader :=bufio.NewReader(F)

eof := false

for!eof {

line,err := bufferReader.ReadString('\n')if err ==io.EOF{

err= nileof= true}else if err != nil{

fmt.Printf("parse file error\n")return}if len(line) > 1{

line= line[0:len(line)-1]//drop '\n'fileconfig := strings.Split(line,"=")if len(fileconfig) == 2{

buf, err := ioutil.ReadFile(fileconfig[0])if err != nil{

fmt.Printf("%s load error\n",fileconfig[0])

}else{

filemap[fileconfig[1]] =buf

fmt.Printf("%s load success,key %s\n",fileconfig[0],fileconfig[1])

}

}

}

}if filemap["golang"] == nil{

fmt.Printf("golang not found\n")

}

fmt.Printf("loadfile finish\n")

}

接着是服务其的packet_handler:

func process_client(session *tcpsession.Tcpsession,rpk *packet.Rpacket){

cmd,_ :=rpk.Uint16()if cmd ==request_file {if session.Ud() != nil{

fmt.Printf("already in transfer session\n")

}else{

filename,_ :=rpk.String()

filecontent :=filemap[filename]if filecontent == nil{

fmt.Printf("%s not found\n",filename)

session.Close()

}else{

fmt.Printf("request file %s\n",filename)

tsession := &transfer_session{filecontent:filecontent,ridx:0}

session.SetUd(tsession)

wpk := packet.NewWpacket(packet.NewByteBuffer(64),false)

wpk.PutUint16(file_size)

wpk.PutUint32(uint32(len(filecontent)))

session.Send(wpk,nil)

tsession.send_file(session)

}

}

}else{

fmt.Printf("cmd error,%d\n",cmd)

session.Close()

}

}

如果收到的消息是requestfile,首先查看请求的文件是否存在,如果存在则创建一个文件传输过程transfersession,

并将它与tcpsession绑定,然后发出一个文件大小通告包,紧接着立即调用send_file开始发送文件内容.

func (this *transfer_session)send_file(session *tcpsession.Tcpsession){

remain := len(this.filecontent) -this.ridx

sendsize := 0

if remain >= 16000{

sendsize= 16000}else{

sendsize=remain

}

wpk := packet.NewWpacket(packet.NewByteBuffer(uint32(sendsize)),false)

wpk.PutUint16(transfering)

wpk.PutBinary(this.filecontent[this.ridx:this.ridx+sendsize])

session.Send(wpk,send_finish)

this.ridx+=sendsize

}

sendfile中根据当前发送位置判断还有多少内容需要发送,如果剩余内容小于16000字节就将所剩数据一次性

发出,否则 发送16000字节的数据,并调整发送位置。注意到Send函数带了一个sendfinish函数作为参数,其作用

是当数据包发送 完成后回调send_finish函数.

func send_finish (s interface{},wpk *packet.Wpacket){

session := s.(*tcpsession.Tcpsession)

tsession := session.Ud().(*transfer_session)iftsession.check_finish(){

session.Close()return}

tsession.send_file(session)

}

send_finish的作用是判断文件是否已经发送完,如果发完断开连接,否则接着发送剩余部分.

总结一下,golang用来编写服务器应用还是相当方便的,很多细节问题在语言层面或系统库里已经帮你解决掉了

,可以将主要的 精力放在逻辑的处理上.

有疑问加站长微信联系(非本文作者)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Golang中,可以通过使用`net/http`包来读取前端传输的文件内容。 首先,服务端需要设置一个HTTP路由处理函数来接收前端传输的文件。这可以通过使用`http.HandleFunc()`函数来实现。在路由处理函数中,可以使用`request.ParseMultipartForm()`函数来解析前端发送的multipart/form-data类型的表单数据。 示例代码如下所示: ```go package main import ( "net/http" "fmt" ) func fileHandler(w http.ResponseWriter, r *http.Request) { err := r.ParseMultipartForm(32 << 20) // 设置最大文件大小为32MB if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } file, _, err := r.FormFile("file") // 获取文件内容 if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer file.Close() // 处理文件内容,例如保存至本地或上传至云端 // ... fmt.Fprint(w, "文件上传成功") } func main() { http.HandleFunc("/upload", fileHandler) http.ListenAndServe(":8080", nil) } ``` 在上述代码中,`fileHandler`函数用于处理前端传输的文件数据。通过调用`r.FormFile("file")`可以获取到文件的内容。接下来,你可以根据具体的需求对文件内容进行处理,例如保存至本地或上传至云端。 最后,通过调用`http.HandleFunc()`函数设置服务器的路由处理函数,并使用`http.ListenAndServe()`函数监听指定的端口,等待客户端的请求。 这样,当前端向服务端发送文件内容时,服务端可以通过上述代码读取并处理文件内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值