这个问题困扰了我一天,不知道是什么原因。还好网上有大佬解决了,参考博客在最下方。
采用dubbo对MultipartFile文件进行传输时,会报invoke method 错误,是因为dubbo并不能跨系统传递这个对象,可以采用Hessian
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.7</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
<exclusions>
<exclusion>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
要注意,jetty包中要排除servlet-api包的依赖,否则会报错,Tomcat不能正常启动。
另外,补充一下,我在interface层,无论如何也用不了MultipartFile这个类,但是发现在Service层可以用,这时候对比发现,Service层比Interface层多了Spring的相关依赖,所以想了一天,终于解决了
添加依赖
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
修改springmvc.xml
<!-- 多部分文件上传 文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="4096" />
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
我的applicationContext-service.xml
<!-- 使用dubbo发布服务 -->
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="taotao-manager" />
<dubbo:registry protocol="zookeeper" address="192.168.25.128:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="hessian" port="20887"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.taotao.service.TestService" ref="testServiceImpl" />
<dubbo:service interface="com.taotao.service.ItemService" ref="itemServiceImpl" />
<dubbo:service interface="com.taotao.service.ItemCatService" ref="itemCatServiceImpl"/>
<dubbo:service protocol="hessian" interface="com.taotao.service.PictureService" ref="pictureServiceImpl" />
我的springMvc.xml
<!-- 引用dubbo服务 -->
<dubbo:application name="taotao-manager-web"/>
<dubbo:registry protocol="zookeeper" address="192.168.25.128:2181"/>
<!--在服务层和表现层都可以设置超时时间。-->
<dubbo:reference interface="com.taotao.service.TestService" id="testService" timeout="300000" />
<dubbo:reference interface="com.taotao.service.ItemService" id="itemService" timeout="300000"/>
<dubbo:reference interface="com.taotao.service.ItemCatService" id="itemCatService" timeout="300000"/>
<dubbo:reference protocol="hessian" interface="com.taotao.service.PictureService" id="pictureService" timeout="1000000" />
发现能传递这个对象了,但是最后发现MultipartFile.getInputStream() 拿不到InputStream了,用byte数组来传递这个InputStream。
1.修改PictureService
package com.taotao.service;
import com.taotao.common.pojo.PictureResult;
import org.springframework.web.multipart.MultipartFile;
/**
* @Author LH
* @Description 上传图片的接口
* @Date 13:27 2020/9/6
* @Param
* @return
**/
public interface PictureService {
PictureResult uploadPicture(byte[] pic,MultipartFile uploadFile);
}
2.修改PictureServiceImpl
package com.taotao.service.impl;
import com.taotao.common.pojo.PictureResult;
import com.taotao.common.util.FtpUtil;
import com.taotao.common.util.IDUtils;
import com.taotao.service.PictureService;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
/**
* @ClassName : PictureServiceImpl
* @Description : 图片上传服务实现类
* @Author : LH
* @Date: 2020-09-05 17:50
* @Version: 1.0
*/
@Service
public class PictureServiceImpl implements PictureService {
@Value("${FTP_ADDRESS}")
private String FTP_ADDRESS;
@Value("${FTP_PORT}")
private Integer FTP_PORT;
@Value("${FTP_USERNAME}")
private String FTP_USERNAME;
@Value("${FTP_PASSWORD}")
private String FTP_PASSWORD;
@Value("${FTP_BASE_PATH}")
private String FTP_BASE_PATH;
@Value("${IMAGE_BASE_URL}")
private String IMAGE_BASE_URL;
@Override
public PictureResult uploadPicture(byte[] pic, MultipartFile uploadFile) {
PictureResult pictureResult = new PictureResult();
if (pic == null || pic.length == 0) {
pictureResult.setError(1);
pictureResult.setMessage("空文件");
return pictureResult;
}
//拿到上传文件的二进制数组inputStream
InputStream inputStream = new ByteArrayInputStream(pic);
//上传文件的名称
String oldName = uploadFile.getOriginalFilename();
//使用IDUtils工具类生成新名称
String newName = IDUtils.genImageName();
//新名称加上旧名称扩展名
newName = newName + oldName.substring(oldName.lastIndexOf("."));
//创建一个以日期命名的文件目录"/2019/3/21"
String imagePath = new DateTime().toString("/yyyy/mm/dd");
//上传文件到图片服务器
boolean result = FtpUtil.uploadFile(FTP_ADDRESS, FTP_PORT, FTP_USERNAME, FTP_PASSWORD, FTP_BASE_PATH,
imagePath, newName, inputStream);
//返回格式参考KindEditor
String url = IMAGE_BASE_URL + imagePath + "/" + newName;
if (!result) {
pictureResult.setError(1);
pictureResult.setMessage("文件上传失败");
return pictureResult;
} else {
pictureResult.setError(0);
pictureResult.setUrl(url);
return pictureResult;
}
}
}
3.修改PictureController,把上传的文件转换成二进制数组,
package com.taotao.controller;
import com.taotao.common.pojo.PictureResult;
import com.taotao.common.util.JsonUtils;
import com.taotao.service.PictureService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* @ClassName : PictureController
* @Description : 上传图片Controller
* @Author : LH
* @Date: 2020-09-05 18:30
* @Version: 1.0
*/
@Controller
public class PictureController {
@Autowired
private PictureService pictureService;
@RequestMapping("/pic/upload")
@ResponseBody
public String upload(MultipartFile uploadFile) {
byte[] pic = new byte[0];
try {
pic = uploadFile.getBytes();
} catch (IOException e) {
e.printStackTrace();
}
PictureResult pictureResult = pictureService.uploadPicture(pic, uploadFile);
String result = JsonUtils.objectToJson(pictureResult);
return result;
}
}
做文件上传功能时,dubbo对MultipartFile文件传输时,一个bug:Fail to decode request due to: RpcInvocation