代码之家  ›  专栏  ›  技术社区  ›  Karlom

无法将文件(type*multipart.fileheader)用作ioutil.writefile的参数中的type[]byte

  •  0
  • Karlom  · 技术社区  · 6 年前

    我知道如何上传一个文件,但现在我试图在同一个golang函数中上传多个文件。

    这是我的代码:

    func PhotoCreatePOST(w http.ResponseWriter, r  *http.Request) {
        var err error
    
    r.ParseMultipartForm(32 << 20) // 32MB is the default used by FormFile
    fhs := r.MultipartForm.File["files"]
    
    var fileNames []string
    var filename string
    var ext string
    for _, file := range fhs { //Iterate over multiple uploaded files
        if err != nil {
            log.Fatal(err)
        } else {
            dir, err := os.Getwd()
            if err != nil {
                log.Fatal(err)
            }
            ext = strings.ToLower(path.Ext(file.Filename))
    
            filename = path.Join(random.RandString(10) + ext)
    
            destFolder := "/media/photos"
            if _, err := os.Stat(destFolder); os.IsNotExist(err) {
                os.Mkdir(destFolder, 0755)
            }
    
            //destination Path. The string which is Saving in DB
            savePath := destFolder + "/" + filename
    
            err = ioutil.WriteFile(savePath, file, 0777) //<--Here is the problem
            if err != nil {
                log.Println(err)
                io.WriteString(w, err.Error())
                return
            }
    
        }
    }
    
    //Add file url to the slice
    fileNames = append(fileNames, filename)
    

    }

    但我有个错误:

    cannot use file (type *multipart.FileHeader) as type []byte in argument to ioutil.WriteFile
    

    我试着读 file 变成这样的字节:

    b, err := ioutil.ReadFile(file) 
        if err != nil {
            fmt.Print(err)
        }
    

    拯救 b 而不是 文件 .

    但后来我又犯了一个错误

    can not read *multipart.Fileheader as string 
    

    我该怎么解决?

    0 回复  |  直到 6 年前
        1
  •  0
  •   Alex Guerra    6 年前

    大致就是这样做的。

    fileHeaders := r.MultipartForm.File["files"]
    var fileNames []string
    
    for _, fileHeader := range fileHeaders {
        file, err := fileHeader.Open()
        if err != nil {
            return err
        }
        defer file.Close()
    
        // Generate the destination filename randomly. Using even the passed
        // extension is a security vulnerability unless you have a whitelist.
        dest, err := ioutil.TempFile("/media/photos", "")
        if err != nil {
            return err
        }
        defer dest.Close()
    
        if _, err := io.Copy(dest, file); err != nil {
            return err
        }
    
        fileNames = append(fileNames, dest.Name())
    }
    
        2
  •  0
  •   Karlom    6 年前

    好吧,多亏了 this 很好的博客文章,我找到了我的答案,这里是完整的解决方案:

    // PhotoCreatePOST saves multiple photo uploads
    func PhotoCreatePOST(w http.ResponseWriter, r *http.Request) {
    
    
        err := r.ParseMultipartForm(100000)
        if err != nil {
            fmt.Println("error parsing multiplepart form", err)
            return
        }
    
        files := r.MultipartForm.File["files"]
    
        for i, _ := range files { //Iterate over multiple uploaded files
    
            file, err := files[i].Open()
            defer file.Close()
            if err != nil {
                fmt.Println("error opening file ", err)
                return
            }
    
            ext := path.Ext(files[i].Filename)
    
            //TODO: Verify extension is valid
    
            filename := GetRandomString(10) + ext
    
            //create destination file making sure the path is writeable.
            dst, err := os.Create("media/photos/" + filename)
            defer dst.Close()
            if err != nil {
                fmt.Println("error creating destination ", err)
                return
            }
    
            //copy the uploaded file to the destination file
            if _, err := io.Copy(dst, file); err != nil {
                fmt.Println("error copying file", err)
                return
            }
    
            fmt.Println("Image upload success: ", files[i].Filename)
        }
    
        fmt.Println("all are uploaded")
    
        PhotoCreateGET(w, r)
        return 
    
    }
    
    //Generate random filename (never trust user input!)
    var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789")
    
    // GetString returns a random string
    func GetRandomString(n int) string {
        rand.Seed(time.Now().UnixNano())
        b := make([]rune, n)
        for i := range b {
            b[i] = letterRunes[rand.Intn(len(letterRunes))]
        }
        return string(b)
    }
    

    上传表格:

    <form method="post" action="/create/photo" enctype="multipart/form-data">
            <input type="file"  name="files"  multiple>
            <input type="hidden" name="token" value="{{.token}}">
            <button title="submit" type="submit" >Save </button>
    </form>
    

    沃伊拉希望能为其他人节省一些时间。