【问题标题】:Golang net/http uploading large files, undefined errorsGolang net/http 上传大文件,未定义错误
【发布时间】:2017-11-12 12:48:21
【问题描述】:

在将大文件上传到使用 golang 的默认 net/http 包制作的服务器时,我遇到了一个很难调试的错误。上传代码如下:

    uploadForm.onsubmit = () => {
        const formData = new FormData(uploadForm);
        const isPublic : boolean = (<HTMLInputElement>document.getElementById('public_switch')).checked;
        formData.append('file', (<HTMLInputElement>document.getElementById('file')).files[0]);
        formData.append('compression', (<HTMLInputElement>document.getElementById('compression')).value);
        formData.append('public', String(isPublic));
        const xhr = new XMLHttpRequest();
        xhr.open("POST", "/upload/");
        xhr.send(formData);
        xhr.onreadystatechange = function() {
            console.log(xhr.responseText);
        }
    }

我有一个用 golang 编写的服务器,我开始如下:

var server = &http.Server{
    Addr:         ":" + Configuration.Port,
    ReadTimeout:  300 * time.Second,
    WriteTimeout: 300 * time.Second,
    ReadHeaderTimeout: 300 * time.Second,
    MaxHeaderBytes: 500000000}

http.HandleFunc("/upload/", uploadFile)

server.ListenAndServe()

最后我接受并使用以下代码解析文件

func uploadFile(w http.ResponseWriter, r *http.Request) {
    //Parsing the upload arguments into the values we shall be working with
    r.ParseMultipartForm(5000000000000000)

    file, _, err := r.FormFile("file")
    //etc

现在,代码本身在 'r.FormFile("file")' 处失败,并带有非常描述性的错误消息:“multipart: NextPart: EOF”

是否有某种文件限制或超时设置,我可能没有在 go 代码或 javascript 中设置?我要上传的文件约为 1.7GB,因此显然符合 http 支持的限制。

知道如何在不必深入研究 FormFile 或捕获请求本身的情况下更好地调试此问题吗?该代码适用于较小的文件(几 Mb​​)。

【问题讨论】:

  • ReadTimeout设置为5 mins后,是否可以在超时前传输1.7GB文件?
  • 开始传输后约 10 秒内出现错误。它是在 lo 上完成的,所以我认为超时不是问题,我只是将其设置为 5 分钟以解决问题。
  • 内容似乎没有发送到服务器。单独测试服务器。请查看stackoverflow.com/a/33809474 并尝试一下。
  • 两个故障排除提示:您可以尝试使用不同的客户端上传数据。 Wireshark 会告诉你哪一方断开了连接。
  • 好的,所以,显然问题是(现在我想起来很明显),这里:formData.append('file', (document.getElementById('file')) .files[0]);

标签: javascript file http typescript go


【解决方案1】:

好的,所以,回答我自己的问题,以防这些东西再次出现。

问题在于 javascript 方面很差,我担心它与表单和文件的 web api 并没有真正达到标准有关。

这是我在javascript方面提出的解决方案:

const uploadFile = (form_id: string) => {
    const uploadForm: HTMLFormElement = <HTMLFormElement>document.getElementById(form_id);
    document.getElementById("submit_form").addEventListener("click", function(e) {
        e.preventDefault()

        let reader: FileReader = new FileReader();
        reader.readAsArrayBuffer((<HTMLInputElement>document.getElementById('file')).files[0]);

        reader.onload = function(evt) {

            const formData = new FormData(uploadForm);
            const isPublic: boolean = (<HTMLInputElement>document.getElementById('public_switch')).checked;
            formData.append('file', (<any>evt.target).result);
            formData.append('compression', (<HTMLInputElement>document.getElementById('compression')).value);
            formData.append('public', String(isPublic));
            const xhr = new XMLHttpRequest();
            xhr.open("POST", "/upload/");
            xhr.send(formData);
            xhr.onreadystatechange = function() {
                console.log(xhr.responseText + '  \n status is: ' + xhr.statusText);
            }

        };
    });

}

确实很简单,但是花了很长时间才找到,因为在典型的 javascipt 社区精神中,所有在线示例都乱七八糟。

应该使用 FileReader 对象来处理大文件,该对象基本上是这样调用的:

 let reader = new FileReader();
        reader.readAsArrayBuffer(dom_element_with_file_input.files[0]);

然后它就像任何其他异步 Web api 一样使用:

    reader.onload = function(e) {
const your_file = e.target.result
    }

变量“your_file”然后用于您想对文件执行的任何操作。在我的情况下,它是这样附加到表单数据的:

        reader.onload = function(e) {
    const your_file = e.target.result
const formData = new FormData(dom_element_of_type_form);
formData.append('my_file', your_file);
formData.append('other_stuff', 'a string with metadata');
        }

我将此作为示例,因为我实际上找不到任何带有文件阅读器 API 的清晰示例的帖子,期望那些在数百行代码中杂乱无章的帖子。我几乎遵循 T 的例子就是这里:

https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications。但为了提高速度,我使用了“readAsArrayBuffer”。

最后一点是阅读器 API 似乎很慢并且消耗大量资源,这意味着对于任意文件大小的浏览器可能会简单地崩溃,我遇到了 chromioum 的这个问题,但我仍然无法修复它,所以我愿意接受建议,如果我找到解决浏览器崩溃的方法(或者至少是一种优雅地处理它们的方法),我会更新问题并将其标记为答案,同时如果有人找到我的答案的副本或者修复浏览器崩溃的方法请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-16
    • 2017-03-28
    • 1970-01-01
    • 2014-05-24
    • 2012-09-01
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    相关资源
    最近更新 更多