无法使用GOLANG和POLYMER http在服务器上保存上传的文件:没有这样的文件

时间:2016-10-10 09:20:07

标签: go polymer vaadin

我正在使用vaadin上传来上传带有聚合物的Web应用程序上的文件。我正在使用golang作为后端。

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

我检查了vaadin上传中使用的编码类型是 multipart / form-data 。 我的golang代码如下。

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)
    }
}

它在服务器端出现错误 http:没有这样的文件。我检查了当提供的文件字段名称不在请求中或文件字段中时,FormFile返回此错误。

如何更正表单文件名。虽然前端的一切看起来都很好 enter image description here

3 个答案:

答案 0 :(得分:2)

进行了快速测试,看来vaadin-upload使用file作为文件的表单数据参数名称。所以在行

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

uploadFile替换为file,它应该有效。

documented on the vaadin homepage

  

为了支持同步上传,我们不是重复使用相同的FormData和XMLHttpRequest,而是为每个文件创建一个新的。因此,服务器只考虑每个请求接收一个文件。

但是,我没有看到记录的参数名称(file),所以为了安全起见,您应该编写代码,以便它不会使用该名称,例如

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
        ...
    }
}

答案 1 :(得分:1)

为那些面临同样问题的人回答我自己的问题。找到一些可以在不知道键值的情况下访问文件的代码。

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))))  
           }  
      }  
 } 

答案 2 :(得分:0)

使用与HTML标记中存在的r.FormFile(“ selectedFile”)完全相同的名称。密钥映射到前端HTML标记中使用的输入名称。

以下是我的实现:

<file
    type="file"
    name="selectedFile"
/>

const (
    S3_REGION = "Your region"
    S3_BUCKET = "Your Bucket Name"
)

func uploadFile(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Uploading File")
    r.ParseMultipartForm(32 << 20)

    file, handler, err := r.FormFile("selectedFile") // 
    if err != nil {
            fmt.Println("Error Retrieving the File")
            fmt.Println(err)
            return
    }

    defer file.Close()

    fmt.Printf("Uploaded File: %+v\n", handler.Filename)
    fmt.Printf("File Size: %+v\n", handler.Size)
    fmt.Printf("MIME Header: %+v\n", handler.Header)

    s, err := session.NewSession(&aws.Config{Region: aws.String(S3_REGION)})
    if err != nil {
        log.Fatal(err)
    }

    var size int64 = handler.Size
    buffer := make([]byte, size)
    file.Read(buffer)

    _, err = s3.New(s).PutObject(&s3.PutObjectInput{
        Bucket:               aws.String(S3_BUCKET),
        Key:                  aws.String(handler.Filename),
        ACL:                  aws.String("private"),
        Body:                 bytes.NewReader(buffer),
        ContentLength:        aws.Int64(size),
        ContentType:          aws.String(http.DetectContentType(buffer)),
        ContentDisposition:   aws.String("attachment"),
        ServerSideEncryption: aws.String("AES256"),
    })       
}