【问题标题】:Not able to save uploaded file on server using GOLANG and POLYMER http: no such file无法使用 GOLANG 和 POLYMER http 在服务器上保存上传的文件:没有这样的文件
【发布时间】:2017-02-18 16:26:39
【问题描述】:

我正在使用 vaadin upload 在带有聚合物的 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 返回此错误。

如何更正我的表单文件名。尽管前端看起来一切都很好

【问题讨论】:

  • 1.找出您的代码在哪里失败。 2. 确保像"./test/"+handler.Filename 这样的东西实际上产生了适合写作的东西(例如 ./test 必须存在)。
  • 我的代码在这部分文件、处理程序、错误中失败:= r.FormFile("uploadFile")
  • 这就是我想知道的我该如何处理。我不知道在这里写什么 FormFile("WHAT!!").因此,代码给出错误
  • 嗯,这是一个 vaadin-only 问题。转储请求并查看。或者使用浏览器的开发者工具跟踪浏览器的功能。
  • 您可以添加完整的错误行吗?只是为了检查哪条线路出现故障。另外,我在您的 html 标记中看不到 name 字段,请记住属性 name 的值必须与 r.FormFile("value_name") 相同

标签: go polymer vaadin


【解决方案1】:

做了一个快速测试,似乎vaadin-upload 使用file 作为文件的表单数据参数名称。所以就行了

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

file 替换uploadFile,它应该可以工作。

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

【讨论】:

  • 感谢您的回答。是的,你是对的。发布此问题后,我发现一些代码与您在不知道键值的情况下上传的代码相同。
  • 什么头疼,我遇到的问题是只有一个文件会上传,其他文件仍然是 cero 字节,谢谢!!
【解决方案2】:

为面临同样问题的人回答我自己的问题。找出一些不知道键值就可以访问文件的代码。

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

【讨论】:

  • 感谢您的最终实施。虽然为未来的程序员发布您的最终解决方案非常好,但接受的答案应该发给@ain。
【解决方案3】:

使用与 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"),
    })       
}

【讨论】:

    猜你喜欢
    • 2022-07-27
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 2013-01-28
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多