Go Web5. 处理文件上传

表单上传

为保证表单上传文件成功,需要添加表单form的enctype属性,enctype属性有三种:

application/x-www-form-urlencoded    表示在发送前编码所有字符(默认)

multipart/form-data    表示不对字符编码(表单上传时必须使用这个)

text/plain    空格转换为”+”加号,但不对特殊字符编码

一、服务端处理

func upload(w http.ResponseWriter, r *http.Request) {

    r.ParseMultipartForm(32 << 20)    // maxMemory

    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

    }

    io.Copy(f, file)

}

处理文件上传我们需要调用r.ParseMultipartForm,里面的参数表示maxMemory,调用ParseMultipartForm之后,上传的文件存储在maxMemory大小的内存里面,如果文件大小超过了maxMemory,那么剩下的部分将存储在系统的临时文件中。

通过r.FormFile获取上面的文件句柄,然后实例中使用了io.Copy来存储文件。

上传文件主要的三步处理

1、表单中增加enctype=”multipart/form-data”;

2、服务端调用r.ParseMultipartForm,把上传的文件存储在内存和临时文件中;

3、使用r.FormFile获取文件句柄,然后对文件进行存储等处理。

FileHander数据结构

文件handler是multipart.FileHeader,结构信息如下:

type FileHeader struct {

    Filename    string

    Header    textproto.MIMEHeader

    // contains filtered or unexported fields

}

比如:

map[Content-Type:[application/pdf] Content-Disposition:[form-data; name=”file”; filename=”coffee.pdf”]]

二、客户端处理

package main

import (

    “bytes”

    “fmt”

    “io”

    “io/ioutil”

    “mime/multipart”

    “net/http””os”

)

func postFile(filename string, targetUrl string) error {

    bodyBuf := &bytes.Buffer{}

    bodyWriter := multipart.NewWriter(bodyBuf)

    // 读取文件到缓存

    fileWriter, err := bodyWriter.CreateFormFile(“uploadfile”, filename)

    if err != nil {

        fmt.Println(“err writing to buffer”)

        return err

    }

    // 打开句柄

    fh, err := os.Open(filename)

    if err != nil {

        fmt.Println(“error opening file”)

        return err

    }

    defer fh.Close()

    // io copy

    _, err = io.Copy(fileWriter, fh)

    if err != nil {

        fmt.Println(“error copy file”)

        return err

    }

    contentType := bodyWriter.FormDataContentType()

    bodyWriter.Close()

    resp, err := http.Post(targetUrl, contentType, bodyBuf)

    if err != nil {

        return err

    }

    defer resp.Body.Close()

    resp_body, err := ioutil.ReadAll(resp.Body)

    if err != nil {

        fmt.Println(“error ioread file”)

        return err

    }

    fmt.Println(resp.Status)

    fmt.Println(string(resp_body))

    return nil

}

func main() {

    target_url := “http://localhost:9090/upload”

    filename := “coffee.pdf”

    postFile(filename, target_url)

}

客户端通过multipart.Write把文件的文本流写入一个缓存中,然后调用http的Post方法把缓存传到服务器。

    原文作者:laigw
    原文地址: https://www.jianshu.com/p/50337287e859
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞