微信小程序上传图片至服务器Springboot接收格式的问题

微信小程序上传图片至服务器Springboot

  • 需求:通过微信小程序上传图片到服务器,保存至服务器。

  • 实现

    • Wxml
    <button bindtap="choose">选择图片</button>
    
    • js
      choose:function(){
        console.log(1)
        wx.chooseImage({
          
          count: 1,
          sizeType:["compressed","original"],
          sourceType:["album","camera"],
    
          success:function(res){
              console.log(res)
              const filePath = res.tempFilePaths[0];
              wx.uploadFile({
                filePath: filePath,
                name: "123",
                url: 'http://xxxx:8080/upload',
                header:{'Content-Type':'application/x-www-form-urlencoded'},
                method:'post',
                success:function(res){
                  console.log(res)
                },
                fail:function(res){
                  console.log(res)
                }
              })
          }
        })
      }
    
    • uploadController
    package com.example.demo;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.UUID;
    
    @RestController
    public class UpLoadController {
        @RequestMapping("/upload")
        public Map<String,String> upload(@RequestParam("file") MultipartFile file ){
            Map<String,String> resultMap = new HashMap<>();
            String path = "/Users/lingg/Desktop/";
            String fileName = file.getOriginalFilename();
            String suffixName = fileName.substring(fileName.indexOf("."));
            fileName = UUID.randomUUID()+suffixName;
            System.out.println("fileName"+fileName);
            System.out.println("fileType:"+suffixName);
            File targetFile = new File(path);
            if(!targetFile.exists()){
                targetFile.mkdir();
            }
            File saveFile = new File(targetFile,fileName);
            try{
                file.transferTo(saveFile);
                System.out.println("上传成功");
                String path1 = path+fileName;
                System.out.println(path1);
                resultMap.put("result","success");
                resultMap.put("path",path1);
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("执行失败");
                resultMap.put("result","failed");
                resultMap.put("path","null");
    
            }
            return resultMap;
        }
    }
    
    
    • application.properties
    spring.servlet.multipart.max-file-size=10MB
    spring.servlet.multipart.max-request-size=100MB
    

第一步在本地进行测试,使用Postman进行测试:

url:http://localhost/upload

form-data:

​file:选择本地文件

​ 返回结果:

{
    "result": "success",
    "path": "/Users/liushanlin/Desktop/123071ed-27d2-4367-b451-1e02d5432893.jpeg"
}

image-20210917235441076

​ 已经可以看到图片成功保存在本地:测试成功!

image-20210917235550287

第二步:部署至服务器,同样使用postman进行测试

​ 启动进程,将日志输出到log.txt文件中方便调试:

[root@lingg src]# nohup java -jar demo-0.0.1-SNAPSHOT.jar >log.txt &
[1] 27019
[root@lingg src]# nohup: 忽略输入重定向错误到标准输出端
^C
[root@lingg src]# ps -ef | grep 27019
root     27019 26409 29 22:26 pts/0    00:00:07 java -jar demo-0.0.1-SNAPSHOT.jar
root     27082 26409  0 22:26 pts/0    00:00:00 grep --color=auto 27019
	url:http://域名:端口号/upload

	form-data:

	file:选择本地文件
image-20210918001035162

​ 返回结果:

{
    "result": "success",
    "path": "/usr/local/src/abca08b5-f6f6-4077-95ac-ae91d5cb76a7.jpeg"
}

​ 查看目录下对应的文件:

image-20210918001532411

​ 文件成功上传至本地:上传成功。

第三步:使用微信小程序进行测试:

image-20210918002020649 image-20210918002051629

​ 返回结果:

{errMsg: "chooseImage:ok", tempFilePaths: Array(1), tempFiles: Array(1)}
  errMsg: "chooseImage:ok"
  tempFilePaths: Array(1)
  0: "http://tmp/F5tqcfC9HecR4b038c8febd34d7dd2bf9fd34b09561f.jpg"
  length: 1
  nv_length: (...)
  __proto__: Array(0)
  tempFiles: Array(1)
  0: {path: "http://tmp/F5tqcfC9HecR4b038c8febd34d7dd2bf9fd34b09561f.jpg", size: 30935}
  length: 1
  nv_length: (...)
  __proto__: Array(0)
  __proto__: Object
{statusCode: 400, data: "{"timestamp":"2021-09-17T16:21:00.571+00:00","status":400,"error":"Bad Request","path":"/upload"}", header: {}, cookies: Array(0), errMsg: "uploadFile:ok"}
cookies: Array(0)
length: 0
nv_length: (...)
__proto__: Array(0)
data: "{"timestamp":"2021-09-17T16:21:00.571+00:00","status":400,"error":"Bad Request","path":"/upload"}"
errMsg: "uploadFile:ok"
header:
Connection: "close"
Content-Type: "application/json"
Date: "Fri, 17 Sep 2021 16:21:00 GMT"
Transfer-Encoding: "chunked"
__proto__: Object
statusCode: 400
__proto__: Object
image-20210918002446755

可以看到,HttpCode是400 BadRequest
而且在springboot程序上打上断点完全没有反应。

​ 目前还没有找出什么原因,网上找了一下说是请求url太长导致的,个人觉得也可能是因为小程序发送的请求参数和Controller的参数类型不一致导致的。

先把坑留在这里,明天有空再慢慢排查!希望有懂的大神能指点一二!万分感谢!

更新:

【已解决】

​ 由于昨天晚上给自己留了坑,所以起了个大早起来填坑!

​ 首先考虑是不是参数的格式不对,因为我查了一下wx.uploadFile()的参数是文件的临时存放地址组成的数组,而uploadController接口中的参数是spring独有的multipartFile,于是接口的参数除了MultipartFile类型,还加上了HttpServletRequest和HttpServletResponse,妄图从中以取参数的方式拿到对应的文件。

@RestController
public class UpLoadController {
    @RequestMapping("/upload")
    public Map<String,String> upload(HttpServletRequest request, HttpServletResponse response,@RequestParam("file") MultipartFile file ){
      Map<String,String> resultMap = new HashMap<>();
			String filePath = request.getParam("filePath");
      System.out.println("filePath");
      return resultMap;
    }
}

结果发现根本没有输出任何东西,也许请求根本没有打到这个接口上来

​ 然后考虑是不是参数不对应?于是我直接去掉了原来的MultipartFile参数,换成了HttpServletRequest和HttpServletResponse,然后输出,发现输出了null!最起码说明能接受到请求了!

​ 那么打上断点Debug一下,看看请求里究竟有什么!

image-20210918090654422

​ 一层一层剥开后发现:请求中居然有这张图片,只不过被一层层封装,并且被我们自己起了一个别的名字而我们自己却不知道!

image-20210918091321656

​ 从图中可以看出,接受到的HttpServletRequest中居然有这个文件,只不过是被封装在一个键为“123”的数组中,这个键名其实就是我们在wx.uploadFiles()请求中参数name的值!

image-20210918091809117

不得不说是自己坑了自己!我们我们只需要在接口的参数前加上注解@RequestParam(“123”)即可!

@RestController
public class UpLoadController {
    @RequestMapping("/upload")
    public Map<String,String> upload(HttpServletRequest request, HttpServletResponse response,@RequestParam("123") MultipartFile file ){
        Map<String,String> resultMap = new HashMap<>();
        String path = "/Users/liushanlin/Desktop/";
        String fileName = file.getOriginalFilename();
        String suffixName = fileName.substring(fileName.indexOf("."));
        fileName = UUID.randomUUID()+suffixName;
        System.out.println("fileName"+fileName);
        System.out.println("fileType:"+suffixName);
        File targetFile = new File(path);
        if(!targetFile.exists()){
            targetFile.mkdir();
        }
        File saveFile = new File(targetFile,fileName);
        try{
            file.transferTo(saveFile);
            System.out.println("上传成功");
            String path1 = path+fileName;
            System.out.println(path1);
            resultMap.put("result","success");
            resultMap.put("path",path1);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("执行失败");
            resultMap.put("result","failed");
            resultMap.put("path","null");

        }
        System.out.println(file);
        return resultMap;
    }
}

哥德巴林猜想:

wx.uploadFile()发送的http请求中将name的值作为参数的名称,文件数组作为参数的值。而name的值又是我们自己去设定的,所以每次取文件的时候,只需要将参数的名称指定为我们在wx.uploadFile( )中设定好的name的值即可成功接收文件!

后来可以看到这一点在微信小程序开发文档中已经讲的很清楚了,猜想正确,至此完美结束。

附:

wx.chooseImage(Object object)

从本地相册选择图片或使用相机拍照。

参数
Object object
属性类型默认值必填说明
countnumber9最多可以选择的图片张数
sizeTypeArray.[‘original’, ‘compressed’]所选的图片的尺寸
sourceTypeArray.[‘album’, ‘camera’]选择图片的来源
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

object.sizeType 的合法值

说明最低版本
original原图
compressed压缩图
object.sourceType 的合法值
说明最低版本
album从相册选图
camera使用相机
object.success 回调函数
参数
Object res
属性类型说明最低版本
tempFilePathsArray.图片的本地临时文件路径列表 (本地路径)
tempFilesArray.图片的本地临时文件列表1.2.0

res.tempFiles 的结构

属性类型说明
pathstring本地临时文件路径 (本地路径)
sizenumber本地临时文件大小,单位 B
Wx.uploadFile(Object object)

​ 将本地资源上传到服务器。客户端发起一个 HTTPS POST 请求,其中 content-typemultipart/form-data

参数
Object object
属性类型默认值必填说明最低版本
urlstring开发者服务器地址
filePathstring要上传文件资源的路径 (本地路径)
namestring文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容
headerObjectHTTP 请求 Header,Header 中不能设置 Referer
formDataObjectHTTP 请求中其他额外的 form data
timeoutnumber超时时间,单位为毫秒2.10.0
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)
object.success 回调函数
参数
Object res
属性类型说明
datastring开发者服务器返回的数据
statusCodenumber开发者服务器返回的 HTTP 状态码

欢迎批评指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值