Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to save uploaded file on server using GOLANG and POLYMER http: no such file

Tags:

go

polymer

vaadin

I am using vaadin upload to upload files on web application with polymer. And I am using golang for back-end.

<vaadin-upload target="../upload" max-files="20" accept="application/pdf,image/*" 
method="POST"> </vaadin-upload>

I checked that encoding type used in vaadin upload is multipart/form-data. My golang code is below.

func upload(w http.ResponseWriter, r *http.Request) {
    fmt.Println("method:", r.Method)
    if r.Method == "GET" {
        crutime := time.Now().Unix()
        h := md5.New()
        io.WriteString(h, strconv.FormatInt(crutime, 10))
        token := fmt.Sprintf("%x", h.Sum(nil))

        t, _ := template.ParseFiles("upload.gtpl")
        t.Execute(w, token)
    } else {
        r.ParseMultipartForm(32 << 20)
        file, handler, err := r.FormFile("uploadFile")
        if err != nil {
            fmt.Println(err)
            return
        }
        defer file.Close()
        fmt.Fprintf(w, "%v", handler.Header)
        f, err := os.OpenFile("./test/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
        if err != nil {
            fmt.Println(err)
            return
        }
        defer f.Close()
        io.Copy(f, file)
    }
}

It gives error on server side http: no such file. I checked this error is returned by FormFile when the provided file field name is either not present in the request or not a file field.

How do I correct my form file name. Although everything seems fine on front-end enter image description here

like image 428
Saransh Avatar asked Oct 10 '16 09:10

Saransh


2 Answers

Did a quick test and it appears that the vaadin-upload uses file as the form data parameter name for the file. So in the line

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

replace uploadFile with file and it should work.

It is documented on the vaadin homepage that

In order to support simultaneous uploads, instead of reusing the same FormData and XMLHttpRequest, we create a new one for each file. It is therefore alright for the server to only consider receiving one file per request.

However, I didn't see the parameter name (file) documented, so to be safe you should write your code so that it wouldn't use the name, ie something like

r.ParseMultipartForm(32 << 20)
m := r.MultipartForm
for _, v := range m.File {
    for _, f := range v {
        file, err := f.Open()
        if err != nil {
            fmt.Println(err)
            return
        }
        defer file.Close()
        // do something with the file data
        ...
    }
}
like image 86
ain Avatar answered Oct 21 '22 00:10

ain


Answering my own question for those who are facing same problem. Found out some code which can access file without knowing the key value.

func UploadHandler(res http.ResponseWriter, req *http.Request) {  
      var (  
           status int  
           err  error  
      )  
      defer func() {  
           if nil != err {  
                http.Error(res, err.Error(), status)  
           }  
      }()  
      // parse request  
     // const _24K = (1 << 20) * 24  
      if err = req.ParseMultipartForm(32 << 20); nil != err {  
           status = http.StatusInternalServerError  
           return  
      } 
        fmt.Println("No memory problem")
      for _, fheaders := range req.MultipartForm.File {  
           for _, hdr := range fheaders {  
                // open uploaded  
                var infile multipart.File  
                if infile, err = hdr.Open(); nil != err {  
                     status = http.StatusInternalServerError  
                     return  
                }  
                // open destination  
                var outfile *os.File  
                if outfile, err = os.Create("./uploaded/" + hdr.Filename); nil != err {  
                     status = http.StatusInternalServerError  
                     return  
                }  
                // 32K buffer copy  
                var written int64  
                if written, err = io.Copy(outfile, infile); nil != err {  
                     status = http.StatusInternalServerError  
                     return  
                }  
                res.Write([]byte("uploaded file:" + hdr.Filename + ";length:" + strconv.Itoa(int(written))))  
           }  
      }  
 } 
like image 44
Saransh Avatar answered Oct 21 '22 00:10

Saransh