将大文件上传到使用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 的问题,但仍然无法解决,所以我我愿意接受建议,如果我找到解决浏览器崩溃的方法(或者至少是一种解决问题的方法),我将更新问题并将其标记为答案,同时如果有人发现我的答案或方法的重复要解决浏览器崩溃的问题,请告诉我。