Http请求头的Content-Type的几种格式和对应的后端参数获取

今天在前后端联调开发过程中,出现了一个后端通过request.getParameterMap()方法获取不到请求参数的问题,所以在此做一个记录,并提出解决方案。

首先,出现问题是因为数据格式为Request Payload,是在react使用axios进行ajax请求的时候出现的,原来,axios中默认请求头的编码为application/json;charset=UTF-8,即Content-Type = "application/json;charset=UTF-8",这个时候可以通过数据流的读取进行参数解析,经测试,方法为通用方法,对于ajax请求适用,代码如下
 

//将请求参数类型为request payload格式的请求参数封装成一个Map
    //该方法为通用方法
    public static Map<String,String> requestPayload2Map(HttpServletRequest request){
        Map<String,String> reqParams = new HashMap<>();
        StringBuilder sb = new StringBuilder();
        //从请求流中读取数据
        try( BufferedReader reader = request.getReader();)
        {
            char[] buffer = new char[1024];
            int len = 0;
            while((len = reader.read(buffer))!=-1){
                sb.append(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("数据为:"+sb.toString());
        JSONObject object = JSONObject.fromObject(sb.toString());
        for (Object key :object.keySet()) {
            reqParams.put((String)key,(String)object.get(key));
        }
        return reqParams;
    }

但是,再后来,通过如下编码对Content-Type进行设置
 

        axios({
            url:url,
            data:{
                userName:username,
                password:password
            },
            method:'post',
            headers:{'Content-Type':'application/x-www-form-urlencoded'}
        })
            .then(response=>{
                const result = response.data
                console.log(result)
            }).catch(error=>{
            console.log(error)
        })

 

这里,我们修改了Content-Type的值,application/x-www-form-urlencoded是窗体数据被编码为名称/值对。这是标准的编码格式我们就有一个疑问,为什么我们的那个方法依然失效呢,经过多种方式测试,发现,我们要使用的方法如果在后台的得到的数据格式为XX1=XXX1&XX2=XXX2,那么我们就可以使用成功了,即通过表单的action方式

当使用表单的action提交的时候,如果设置了属性encType = "multipart/form-data",那么后台获取到的数据格式为:
 

数据为:------WebKitFormBoundaryN4vBMLIkQoIBjLqe
Content-Disposition: form-data; name="usename"

liming
------WebKitFormBoundaryN4vBMLIkQoIBjLqe
Content-Disposition: form-data; name="password"

123456
------WebKitFormBoundaryN4vBMLIkQoIBjLqe--

此时的Content-Type为Content-Type:    multipart/form-data; boundary=----WebKitFormBoundaryN4vBMLIkQoIBjLqe,所以建议在使用ajax的时候,最好使用通用方法进行参数获取,以便少走弯路。。。

Vue3 本身并没有提供合并多个 Range 请求获取的文件块的方法,这需要在后端进行处理。一种常见的做法是在后端将多个 Range 请求合并成一个请求,然后返回一个连续的文件块。如果你使用的是 Node.js 作为后端,你可以使用 `range-parser` 这个库来完成这个功能。该库可以帮助你解析 Range 请求,并将多个请求合并成一个请求。以下是一个示例代码: ```javascript const rangeParser = require('range-parser'); const fs = require('fs'); const filePath = 'path/to/file'; const fileStat = fs.statSync(filePath); const rangeHeader = req.headers.range; const ranges = rangeParser(fileStat.size, rangeHeader); if (ranges === -1) { // 无效的 Range 请求 return res.status(400).end(); } if (ranges === -2) { // 未指定 Range 请求 res.set({ 'Content-Length': fileStat.size, 'Content-Type': 'video/mp4' }); return fs.createReadStream(filePath).pipe(res); } if (ranges.length === 1) { // 单个 Range 请求 const range = ranges[0]; res.status(206); res.set({ 'Content-Range': `bytes ${range.start}-${range.end}/${fileStat.size}`, 'Content-Length': range.end - range.start + 1, 'Content-Type': 'video/mp4' }); return fs.createReadStream(filePath, { start: range.start, end: range.end }).pipe(res); } // 多个 Range 请求 res.status(206); res.set({ 'Content-Type': 'multipart/byteranges; boundary=3d6b6a416f9b5', 'Content-Length': ranges.reduce((total, range) => { return total + `--3d6b6a416f9b5\r\nContent-Type: video/mp4\r\nContent-Range: bytes ${range.start}-${range.end}/${fileStat.size}\r\n\r\n`.length + (range.end - range.start + 1); }, 0) }); res.write('--3d6b6a416f9b5\r\nContent-Type: video/mp4\r\nContent-Range: bytes ' + ranges[0].start + '-' + ranges[0].end + '/' + fileStat.size + '\r\n\r\n'); fs.createReadStream(filePath, { start: ranges[0].start, end: ranges[0].end }).pipe(res, { end: false }); for (let i = 1; i < ranges.length; i++) { res.write('\r\n--3d6b6a416f9b5\r\nContent-Type: video/mp4\r\nContent-Range: bytes ' + ranges[i].start + '-' + ranges[i].end + '/' + fileStat.size + '\r\n\r\n'); fs.createReadStream(filePath, { start: ranges[i].start, end: ranges[i].end }).pipe(res, { end: false }); } res.end('\r\n--3d6b6a416f9b5--\r\n'); ``` 这段代码做了以下几件事情: 1. 使用 `range-parser` 库解析 Range 请求,如果请求无效或未指定 Range,则返回整个文件。 2. 如果请求只有一个 Range,则返回对应的文件块。 3. 如果请求有多个 Range,则返回多个文件块,并使用 `multipart/byteranges` 类型的响应进行分隔。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值