解决Go上传文件报错:找不到Boundary的问题

最近要做一个组件,即接收客户端的请求,经过一系列的封装,将请求发送给真正的服务端器。可以理解为:客户端使用Http的Request的Body存储文件流,将Request发送给服务器。遇到一个问题:传入的是一个文件句柄File,需要转换成byte[]存到request的body中,但是发现boundary找不到,自行在content-Type中加上Boundary字段,发现后台读取不到文件流。

1. 首先自己使用Spring Boot搭了一个简单的server,接收Client发送过来的request,读取body然后输出。启动的是8080端口,path为/hello,代码如下:

2. 客户端的代码:

var file *os.File
file,err = os.Open("src/main/post.txt")
if err != nil {
 fmt.Println(err)
 return
}
defer file.Close()
body := bufio.NewReader(file)
requestWrapper.Request.Body = ioutil.NopCloser(body)

(1).第一步使用os.Open打开一个文件,返回的是一个文件句柄os.File类型

(2)然后使用缓冲池的读取方法NewReader构建一个Reader,此处用的是默认的缓冲池大小:4096,当然可以换做这个方法来主动传入一个缓冲池大小NewReaderSize(rd, defaultBufSize)

(3)因为Request的Body是一个io.ReadCloser类型,所以需要调用ioutil.NopCloser方法将Reader类型转换成ReadCloser。

3. 万事俱备,现在执行客户端代码,发现server端报错:

1533268964_71_w1049_h49.png

即:缺少boundary。

经查阅资料发现,boundary是HttpRequest为multipart类型的contentType设置的一个分隔符,为了使服务器正确识别文件的起始位置。浏览器会自动生成一个随机数作为Boundary,也可以自己制定一个固定的boundary,但要足够复杂,防止与文件中的内容重复,无法正确识别起始位置。

例如,有Boundary的contentType:"Content-Type", "multipart/form-data; boundary=ABCD"

4. 既然缺少boundary,那么就为其添加一个Boundary。

requestWrapper.Request.Header.Set("Content-Type", "multipart/form-data;boundary="+ multipart.NewWriter(bytes.NewBufferString("")).Boundary())

此处的Boundary()函数是Writer提供的一个会返回一个随机数的Boundary

再次启动,发现server端能够接收到请求,但是,打印request的body,发现内容为空!!!

百思不得其解。。。。

5. 查阅资料,说删除自定义的content-Type字段,尝试了一下,竟然成功。

Request.Header.Del("Content-Type")

原因是:

原来 post 请求上传文件的时候是不需要自己设置 Content-Type,会自动给你添加一个 boundary ,用来分割消息主体中的每个字段,如果这个时候自己设置了 Content-Type, 服务器就不知道怎么分割各个字段,因此就会报错。

如果自己设置了content-Type但是又不设置boundary,自然会出现找不到boundary。

所以!让浏览器自己去设置conten-Type。

 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值