使用 go 处理文件上传

我最近开始玩围棋,所以我还是个菜鸟,如果我犯了太多错误,请见谅。我一直试图解决这个问题很长时间,但我只是不明白发生了什么。在我的 main.go 文件中,我有一个 main 函数:


func main() {

    http.HandleFunc("/", handler)

    http.HandleFunc("/submit/", submit)

    log.Fatal(http.ListenAndServe(":8080", nil))

}

处理程序函数如下所示:


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

    data, _ := ioutil.ReadFile("web/index.html")

    w.Write(data)

}

我知道这不是为网站提供服务的最佳方式提交功能如下所示:


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

    log.Println("METHOD IS " + r.Method + " AND CONTENT-TYPE IS " + r.Header.Get("Content-Type"))

    r.ParseMultipartForm(32 << 20)

    file, header, err := r.FormFile("uploadFile")

    if err != nil {

        json.NewEncoder(w).Encode(Response{err.Error(), true})

        return

    }

    defer file.Close()


    out, err := os.Create("/tmp/file_" + time.Now().String() + ".png")

    if err != nil {

        json.NewEncoder(w).Encode(Response{err.Error(), true})

        return

    }

    defer out.Close()


    _, err = io.Copy(out, file)

    if err != nil {

        json.NewEncoder(w).Encode(Response{err.Error(), true})

        return

    }


    json.NewEncoder(w).Encode(Response{"File '" + header.Filename + "' submited successfully", false})

}

问题是,当执行功能的提交,r.Method是GET和r.Header.Get("Content-Type")是一个空字符串,然后继续,直到第一,如果其中r.FormFile返回以下错误: request Content-Type isn't multipart/form-data 我不明白为什么r.Method总是GET和没有内容-类型。我尝试以多种不同的方式执行 index.html,但 r.Method 始终为 GET,而 Content-Type 为空。这是 index.html 中上传文件的函数:


function upload() {

    var formData = new FormData();

    formData.append('uploadFile', document.querySelector('#file-input').files[0]);

    fetch('/submit', {

        method: 'post',

        headers: {

          "Content-Type": "multipart/form-data"

        },

但这也不起作用。我用 Google 搜索过如何使用 fetch() 以及如何从 go 接收文件上传,我发现它们与我的非常相似,我不知道我做错了什么。


慕勒3428872
浏览 182回答 2
2回答

ABOUTYOU

我设法解决了我的问题,所以在这里以防其他人需要它。并感谢@JiangYD 提供使用 curl 测试服务器的技巧。TL; 博士我写了,http.HandleFunc("/submit/", submit)但我正在向/submit(注意缺少的斜线)发出 POST 请求<<这很重要,因为重定向不要自己指定 Content-Type,浏览器会为你做长答案我按照@JiangYD 说的做了,并使用curl 来测试服务器,我用响应更新了我的答案。我发现奇怪的是有一个 301 重定向,因为我没有把它放在那里,我决定使用以下 curl 命令curl -v -F 'uploadFile=@\"C:/Users/raul-/Desktop/test.png\"' -L http://localhost:8080/submit(注意-L)那样 curl 跟随重定向,尽管它再次失败,因为在重定向时,curl 从 POST 切换到 GET 但通过该响应我发现请求/submit被重定向到/submit/,我记得我是这样写的它在main函数中。在修复它仍然失败后,响应是http: no such file并且通过查看net/http代码我发现这意味着该字段不存在,因此我对获得的所有字段名称进行了快速迭代:for k, _ := range r.MultipartForm.File {&nbsp; &nbsp; log.Println(k)}我得到'uploadFile了字段名称,我删除了 curl 命令中的单引号,现在它完美地上传了文件但这并没有结束,我现在知道服务器工作正常,因为我可以使用上传文件,curl但是当我尝试通过托管网页上传文件时,出现错误:no multipart boundary param in Content-Type.所以我发现我应该在标题中包含边界,我将 fetch 更改为这样的:fetch('/submit', {&nbsp; &nbsp; method: 'post',&nbsp; &nbsp; headers: {&nbsp; &nbsp; &nbsp; &nbsp; "Content-Type": "multipart/form-data; boundary=------------------------" + boundary&nbsp; &nbsp; }, body: formData})我像这样计算边界:var boundary = Math.random().toString().substr(2);但是我还是有一个错误:multipart: NextPart: EOF那么你如何计算边界?我阅读了规范https://html.spec.whatwg.org/multipage/forms.html#multipart/form-data-encoding-algorithm并发现边界是由对文件进行编码的算法计算的,在我的情况下是 FormData,FormData API 没有公开获取该边界的方法,但我发现浏览器会multipart/form-data自动添加 Content-Type with和边界,如果您不指定它,所以我从fetch调用中删除了 headers 对象和现在它终于起作用了!

摇曳的蔷薇

完全删除标题实际上有效。尤其是通过 fetch 或 axios 发送请求时。axios.post(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; endpoint + "/api/v1/personalslip",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newSlip&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .then(res => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log(res);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go