golang Client 客户端 大文件上传 (带进度条)

需要用到环形缓冲区进行读写:golang 环形缓冲区

网上的例子大部分都是把文件全部缓存到内存上传,大文件隐患不小,这个的好处就是缓冲区小,全靠流输入输出。

go get github.com/mgr9525/go-ruisutil
func randomBoundary() string {
	var buf [30]byte
	_, err := io.ReadFull(rand.Reader, buf[:])
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", buf[:])
}
/*
 * url:上传地址
 * flpath:上传文件地址
 */
func upload(url,flpath string){
	body := ruisUtil.NewCircleByteBuffer(10240)
	boundary:=randomBoundary()
	boundarybytes := []byte("\r\n--" + boundary + "\r\n")
	endbytes := []byte("\r\n--" + boundary + "--\r\n")

	reqest, err := http.NewRequest("POST", url, body)
	if err != nil { panic(err) }
	reqest.Header.Add("Connection", "keep-alive")
	reqest.Header.Add("Content-Type", "multipart/form-data; charset=utf-8; boundary="+boundary)
	go func() {
		//defer ruisRecovers("upload.run")
		f, err := os.OpenFile(flpath, os.O_RDONLY, 0666)  //其实这里的 O_RDWR应该是 O_RDWR|O_CREATE,也就是文件不存在的情况下就建一个空文件,但是因为windows下还有BUG,如果使用这个O_CREATE,就会直接清空文件,所以这里就不用了这个标志,你自己事先建立好文件。
		if err != nil { panic(err) }
		stat, err := f.Stat()    //获取文件状态
		if err != nil { panic(err) }
		defer f.Close()

		header:=fmt.Sprintf("Content-Disposition: form-data; name=\"upfile\"; filename=\"%s\"\r\nContent-Type: application/octet-stream\r\n\r\n",stat.Name())
		body.Write(boundarybytes)
		body.Write([]byte(header))

		fsz:=float64(stat.Size())
		fupsz:=float64(0)
		buf:=make([]byte,1024)
		for {
			time.Sleep(10*time.Microsecond)//减缓上传速度,看进度效果
			n,err:=f.Read(buf)
			if n>0{
				nz,_:=body.Write(buf[0:n])
				fupsz+=float64(nz)
				progress := strconv.Itoa(int((fupsz / fsz) * 100))+"%"
				fmt.Println("upload:",progress,"|",strconv.FormatFloat(fupsz,'f',0,64),"/",stat.Size())
			}
			if err==io.EOF {
				break
			}
		}
		body.Write(endbytes)
		body.Write(nil)//输入EOF,表示数据写完了
	}()
	resp,err:=http.DefaultClient.Do(reqest)
	if err != nil { panic(err) }
	defer resp.Body.Close()
	if resp.StatusCode==200{
		fmt.Println("上传成功")
	}else{
		fmt.Println("上传失败,StatusCode:",resp.StatusCode)
	}
}

 

调用:

upload("http://localhost:8080/upload","e:\\123.txt")

 

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
可以使用 Golang 的 multipart 包来实现分块接收大文件上传的服务端。具体步骤如下: 1. 定义一个路由,处理客户端上传文件的请求,例如: ```go http.HandleFunc("/upload", uploadHandler) ``` 2. 在 uploadHandler 函数中,使用 multipart 包解析客户端发送的请求,获取上传文件的内容和信息,例如: ```go func uploadHandler(w http.ResponseWriter, r *http.Request) { err := r.ParseMultipartForm(32 << 20) // 限制上传文件大小为 32MB if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } file, header, err := r.FormFile("file") // 获取上传文件的内容和信息 if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer file.Close() // 处理上传文件的内容和信息 // ... } ``` 3. 在处理上传文件的内容和信息时,可以将文件分块读取并保存到本地或者云端存储中,例如: ```go const ( maxChunkSize = 10 * 1024 * 1024 // 限制每个分块大小为 10MB ) func uploadHandler(w http.ResponseWriter, r *http.Request) { // ... totalSize := header.Size // 获取上传文件的总大小 chunks := int(math.Ceil(float64(totalSize) / float64(maxChunkSize))) // 计算需要分成几个块 for i := 0; i < chunks; i++ { chunkSize := maxChunkSize if i == chunks-1 { chunkSize = int(totalSize) - i*maxChunkSize // 最后一个块的大小可能不足 maxChunkSize } chunk := make([]byte, chunkSize) _, err := file.Read(chunk) // 读取分块内容 if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // 将分块内容保存到本地或者云端存储中 // ... } // ... } ``` 这样就可以实现 Golang 分块接收大文件上传的服务端了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值