为了账号安全,请及时绑定邮箱和手机立即绑定

http PUT请求在golang中上传zip文件

http PUT请求在golang中上传zip文件

Go
慕姐8265434 2023-05-15 15:05:30
我的客户端代码基本上是尝试使用 HTTP PUT METHOD 将 tar.gz 文件上传到服务器。但是服务器似乎不喜欢它并且似乎总是向我发送 500 错误响应。以下是代码。我不确定出了什么问题。 func upLoadFileToServer (uploadFileName string) {    tr := &http.Transport{          TLSClientConfig: &tls.Config{InsecureSkipVerify: true},          ExpectContinueTimeout : 30 * time.Second,        }    client := &http.Client{ Transport:tr,                          Timeout: 20 * time.Second}    timeCurrent = time.Now()    fileContents, err := ioutil.ReadFile(uploadFileName)    if err != nil {     log.Println("Failed to Read the File", uploadFileName, err)    }    PutReq, _ := http.NewRequest("PUT", "https://www.example.com/upload", strings.NewReader(string(fileContents)))    PutReq.Header.Set("Content-Type", "application/zip")    PutReq.ContentLength = int64(len(string(fileContents)))    PutReq.Header.Set("Expect", "100-continue")    PutReq.Header.Set("Accept", "*/*")    PutReq.Header.Set("Date", timeCurrent.Format(time.RFC1123))    PutResp, err := client.Do(inventoryPutReq)    }有时我注意到 Connection RESET by PEER 错误。但大多数时候是 500。我使用 POSTMAN 尝试完全相同的请求,它似乎工作正常。
查看完整描述

1 回答

?
GCT1015

TA贡献1827条经验 获得超4个赞

这是一个工作示例。


最有可能的是,它归结为服务器有点简单并且按字面意思获取文件名的事实。并且由于您没有filepath.Base在您的 上使用uploadFileName,因此它上面可能有路径元素。只需将它用于您的文件名以进行测试。


重置可能是由超时引起的。


package main


import (

    "bytes"

    "flag"

    "fmt"

    "io"

    "log"

    "mime/multipart"

    "net"

    "net/http"

    "os"

    "path/filepath"

    "sync"

)


var (

    targetPath string

    filename   string

    port       int

    handlerLog *log.Logger

    mainLog    *log.Logger

)


// This is automatically called after vars have been initialized and before main

func init() {

    flag.StringVar(&targetPath, "target", "./tmp", "target directory for uploads")

    flag.StringVar(&filename, "file", "", "file to upload")

    flag.IntVar(&port, "port", 0, "port to listen on. When 0, a random port is assigned")

    handlerLog = log.New(os.Stdout, "[handler] ", log.LstdFlags)

    mainLog = log.New(os.Stdout, "[main   ] ", log.LstdFlags)

}


// By returning a handler, we have an elegant way of initializing path.

func uploadHandler(path string) http.Handler {


    // We make sure path is an existing directory when the handler takes over

    if s, err := os.Stat(path); err != nil {

        if os.IsNotExist(err) {

            handlerLog.Printf("Target '%s' does not exist. Creating it...", path)

            if cerr := os.MkdirAll(path, 0755); cerr != nil {

                handlerLog.Fatalf("Creating target: %s", err)

            }

        } else {

            handlerLog.Fatalf("Error accessing '%s': %s", path, err)

        }

    } else if !s.IsDir() {

        handlerLog.Fatalf("Target '%s' is not a directory", path)

    }


    // Do NOT use this handler in production!!!

    // It is lacking all sorts of safety measures.

    // However, it is enough to demonstrate.

    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        handlerLog.Println("Handling file upload...")


        handlerLog.Println("Parsing form...")

        if err := r.ParseMultipartForm(32 << 20); err != nil {

            handlerLog.Fatalf("Parsing form: %s", err)

        }

        f, h, err := r.FormFile("file")

        if err != nil {

            handlerLog.Printf("Error accessing file: %s", err)

            http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)

            return

        }

        defer f.Close()


        handlerLog.Println("Opening output file...")

        t, err := os.OpenFile(filepath.Join(path, filepath.Base(h.Filename)), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)

        if err != nil {

            handlerLog.Printf("Opening output file: %s", err)

            http.Error(w, http.StatusText(http.StatusInternalServerError)+": "+err.Error(), http.StatusInternalServerError)

            return

        }

        defer t.Close()


        handlerLog.Println("Copying to output file...")

        if _, err = io.Copy(t, f); err != nil {

            handlerLog.Printf("Copying to output file: %s", err)


            http.Error(w, http.StatusText(http.StatusInternalServerError)+": "+err.Error(), http.StatusInternalServerError)

            return

        }

        handlerLog.Println("Finished handler!")

    })

}


func main() {

    flag.Parse()


    // Check input

    if filename == "" {

        mainLog.Fatal("No filename given. Exiting...")

    }


    mainLog.Println("Setting up upload handler...")

    http.Handle("/upload", uploadHandler(targetPath))


    wg := sync.WaitGroup{}

    wg.Add(1)


    // We want to finish the program after upload, as we only want to demonstrate

    go func() {

        mainLog.Println("Setting up listener...")


        listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))

        if err != nil {

            mainLog.Fatalf("%s", err)

        }

        defer listener.Close()


        port = listener.Addr().(*net.TCPAddr).Port

        mainLog.Printf("Listening to port %d on localhost", port)


        wg.Done()

        http.Serve(listener, nil)

    }()


    buf := bytes.NewBuffer(nil)

    bodyWriter := multipart.NewWriter(buf)


    // We need to truncate the input filename, as the server might be stupid and take the input

    // filename verbatim. Then, he will have directory parts which do not exist on the server.

    fileWriter, err := bodyWriter.CreateFormFile("file", filepath.Base(filename))

    if err != nil {

        mainLog.Fatalf("Creating fileWriter: %s", err)

    }


    file, err := os.Open(filename)

    if err != nil {

        mainLog.Fatalf("Opening file: %s", err)

    }

    defer file.Close()


    if _, err := io.Copy(fileWriter, file); err != nil {

        mainLog.Fatalf("Buffering file: %s", err)

    }


    // We have all the data written to the bodyWriter.

    // Now we can infer the content type

    contentType := bodyWriter.FormDataContentType()


    // This is mandatory as it flushes the buffer.

    bodyWriter.Close()


    // As we wait for the server to spin up, we need to wait here.

    mainLog.Println("Waiting for the listener to be set up...")

    wg.Wait()


    req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("http://127.0.0.1:%d/upload", port), buf)

    if err != nil {

        mainLog.Fatalf("Creating request: %s", err)

    }

    req.Header.Set("Content-Type", contentType)


    client := http.Client{}


    mainLog.Println("Sending file")

    res, err := client.Do(req)

    if err != nil {

        mainLog.Fatalf("Sending file: %s", err)

    }


    mainLog.Printf("Received %s from server. Exiting...", res.Status)

}



查看完整回答
反对 回复 2023-05-15
  • 1 回答
  • 0 关注
  • 266 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信