上传文件完成后一直卡住无法断开连接,代码该如何改呢?

chirst · 2023-03-25 10:17:53 · 1905 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2023-03-25 10:17:53 的主题,其中的信息可能已经有所发展或是发生改变。

package main

import (
    "crypto/rand"
    "fmt"
    ruisUtil "github.com/mgr9525/go-ruisutil"
    "io"
    "net/http"
    "os"
    "strconv"
    "time"
    "context"
)
func randomBoundarys() string {
    var buf [30]byte
    _, err := io.ReadFull(rand.Reader, buf[:])
    if err != nil {
        panic(err)
    }
    return fmt.Sprintf("%x", buf[:])
}
func uploadss(url,flpath string){
    ctx, _ := context.WithCancel(context.Background())
    body := ruisUtil.NewCircleByteBuffer(ctx,10240000)
    boundary:=randomBoundarys()
    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,10240000)
        for {
            time.Sleep(10*time.Microsecond)//减缓上传速度,看进度效果
            n,err:=f.Read(buf)
            fmt.Println(err)
            if err==io.EOF {
                break
            }
            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())
            }

        }
        body.Write(endbytes)
        body.Write(nil)//输入EOF,表示数据写完了
    }()
    resp,err:=http.DefaultClient.Do(reqest)

    fmt.Println(resp)
    if err != nil { panic(err) }
    defer resp.Body.Close()
    if resp.StatusCode==200{
        fmt.Println("上传成功")
    }else{
        fmt.Println("上传失败,StatusCode:",resp.StatusCode)
    }
}


// sample usage
func main() {
    uploadss("http://103.18.10.5:8080/PutFile","D:\\go1.14.3.windows-amd64.zip")
}

QQ图片20230325101716.png


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

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1905 次点击  
加入收藏 微博
5 回复  |  直到 2023-03-27 16:37:39
polaris
polaris · #1 · 2年之前

不需要手动写入 nil 吧?

chirst
chirst · #2 · 2年之前
polarispolaris #1 回复

不需要手动写入 nil 吧?

😂写不写nil 上传完都会卡住无法断开

guokun1998
guokun1998 · #3 · 2年之前

是不是不满足 err==io.EOF

Neightly
Neightly · #4 · 2年之前

200只能说明请求能被处理,不能说明请求已经完成。 比较典型的例子是Docker,200很快就响应了,但是实际上image一直在异步下载。

tuzhiya
tuzhiya · #5 · 2年之前

写法有问题吧。用了协成,那就把协成的状态转出来判断。不要用了协成又不注意处理,只注意用骚操作,不然谁都救不了

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传