Golang随机“意外EOF”错误,阅读multipart,Part

xdyibdwo  于 2023-05-04  发布在  Go
关注(0)|答案(1)|浏览(357)

下面的代码处理一个或多个使用enctype=“multipart/form-data”上传的文件,通常来自网页。我们可以假设,表单部分总是文件。

// Error handling not complete
func (t *Tools) UploadFiles(r *http.Request, uploadDir string) {
    reader, _ := r.MultipartReader()
    for {
        part, err := reader.NextPart()
        if err == io.EOF {
            break
        }
        if err != nil {
            return
        }

        fileName := part.FileName()
        var outfile *os.File
        defer outfile.Close()
        if outfile, err := os.Create(filepath.Join(uploadDir, fileName)); err != nil {
            return
        } else {
            fileSize, err := io.Copy(outfile, part)
            log.Printf("Size: %d FileName: %s Error: %v\n", fileSize, fileName, err)
            if err != nil {
                return
            }
        }
    }
}

当上传多个文件时io.Copy在上面的代码中有时会返回意外的EOF错误。

  • 它从来没有发生时,一个单一的文件上传。当上传的文件数量超过20时,它就开始发生了。每个文件的大小大约为1 MB。

当我们使用r.ParseMultipartFormr.MultipartForm.File,然后使用io.Copy(outfile,header.Open()),其中header是r.MultipartForm.File返回的Hashmap中的value时,不会发生这种情况
有人能指出可能出了什么问题吗?

go版本go1.20达尔文/amd 64

~内森

ktecyv1j

ktecyv1j1#

我认为你应该使用websocket来做这样的事情,因为你永远不知道会有多少文件,请求可能比你预期的要长得多。这种程序可能不会在本地机器上给予,但可能会在服务器上出错。
你可以做的是当用户提交表单时,你可以用javascript处理点击事件,打开一个websocket连接,逐个上传文件,并向用户显示上传了多少文件
这里是一个javascript代码上传一个文件到服务器通过WebSocket连接你可以改变它根据你的需要实际上我是上传excel文件做在数据库中的条目和excel表中的记录超过50000所以我也从服务器发送的进展也.

<form>
    <input type="File" name="catalogues" id="catalogues">
    <input type="button" name="Submit" value="Submit" onclick="SendFile()">
</form>

function SendFile(){
    console.clear()
    start = performance.now();
    const Socket = new WebSocket("ws://localhost:1323/api/v1/catalogue/upload/ws");

    Socket.onopen=function() {
        //authentication
        Socket.send("<Authentication Token>")
        Socket.binaryType="arraybuffer"
        let XlsxFile = document.getElementById('catalogues').files[0];
        Socket.send(XlsxFile)
    };
    Socket.onmessage = function (evt) {
        if(typeof evt.data=="object"){
            const link = document.createElement('a');
            const XlsxFile = new Blob([evt.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
            link.setAttribute('href', URL.createObjectURL(XlsxFile))
            link.setAttribute('download', `response.xlsx`);
            link.innerText="Download"
            document.body.append(link)
            end = performance.now();
            timeTaken = end - start;
            console.log("Function took " +
                timeTaken + " milliseconds");
        }
        console.log(evt.data)
    };

    Socket.onclose = function() {
        // websocket is closed.
        console.log("Connection is closed...");
    };
    Socket.onerror = function(e) {

        console.log(e);

    };
}

你应该在服务器端做的是升级到WebSocket的连接,并通过你使用的任何身份验证方法进行身份验证,然后逐个处理文件。

for {
    mt, message, err := ws.ReadMessage()
    if err != nil {
        return nil, errorx.WrapDefaultError(err.Error())
    }
    
    if mt != websocket.BinaryMessage {
        ws.WriteMessage(ws.TextMessage,[]byte("Invalid Message Type : " + string(message)))
        break
    }
}

然后你可以读取这些字节并将其写入文件来完成工作
一件事是你需要在go例程中做这件事,因为服务器连接将被关闭,但WebSocket连接将是持久的。
你可以使用gorilla websocket库来轻松地做你的工作,这个库是存档的,但它工作得很完美,也没有其他好的选择

相关问题