将大文件上传到使用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)也可以正常工作。

最佳答案

好,所以,如果这个问题再次出现,请回答我自己的问题。

问题出在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-community精神中,所有在线示例都杂乱无章。

大文件的处理应使用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');
        }

我将其作为示例,因为我实际上找不到任何带有文件Reader API清晰示例的帖子,期望那些实际上成百上千行的代码困惑不堪。我几乎在T后面跟随的例子就是这里的例子:

https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications。但是我改用'readAsArrayBuffer'来提高速度。

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

10-07 19:52
查看更多