File文件转发

2019, Feb 09    

File文件转发

项目中,采用的是基于Spring Cloud微服务架构,消费者需要转发请求参数到生产者,但是,要转发的文件是MutipartFile类型。

MutipartFile是spring里面定义的接口,封装了用户在上传图片时所包含的所有信息。直接用restTemplate转发会抛异常。

有两个解决思路:1.把MutipartFile写到本地,然后restTemplate上传。2.不用restTemplate,用HttpClient发送字节数组(生产者仍然可以用file接收),省去写文件和读文件的开销

出于性能考虑,选择后者。

1.HttpClien模拟表单转发请求参数

@RequestMapping(value = "addContactByExcel", method = RequestMethod.POST)
    public String addContactByExcel(@RequestParam("userId") String userId,
                                    @RequestParam("groupName") String groupName,
                                    @RequestParam("excel") MultipartFile excel) {

        try {
            String url = ServiceDiscover.loadBlance("department-service") + "/addressList/addContactByExcel";
            // 自定义ContentType,用来传输中文
            ContentType CHINESE_CONTENT_TYPE = ContentType.create("text/plain", Consts.UTF_8);

            // 模拟发送psot表单
            HttpPost post = new HttpPost(url);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            builder.addBinaryBody("excel", excel.getBytes(), ContentType.MULTIPART_FORM_DATA, "excel.xls");
            builder.addTextBody("userId", userId, ContentType.TEXT_PLAIN);
            builder.addTextBody("groupName", groupName, CHINESE_CONTENT_TYPE);
            org.apache.http.HttpEntity entity = builder.build();
            post.setEntity(entity);
            CloseableHttpClient client = HttpClients.createDefault();
            HttpResponse response = client.execute(post);
            return IOUtils.toString(response.getEntity().getContent(), "utf-8");
        } catch (Exception e) {
            return e.getMessage();
        }
    }

2.自定义服务发现

package cn.bookcycle.consumer.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * ServiceDiscover
 *
 * @author Flynn
 * @version 1.0
 * @description 手动服务发现
 * @email liufenglin@163.com
 * @date 2019/2/8
 */
@Component
public class ServiceDiscover {

    private static DiscoveryClient discoveryClient;

    @Autowired
    public void setDiscoveryClient(DiscoveryClient discoveryClient) {
        ServiceDiscover.discoveryClient = discoveryClient;
    }

    /**
     * 对指定服务进行负载均衡选择
     *
     * @param serviceName 服务名
     * @return 生产者的地址
     * @throws Exception 没有服务的生产者异常
     */
    public static String loadBlance(String serviceName) throws Exception {
        List hosts = hosts(serviceName);
        if (hosts.size() == 0) {
            throw new Exception("no service producer");
        }
        int size = hosts.size();
        return hosts.get(new Random().nextInt(size)).toString();
    }

    /**
     * 获取服务的所有IP地址
     *
     * @param serviceName 服务名
     * @return 服务的所有IP地址构成的List,List的size可以为0
     */
    private static List hosts(String serviceName) {
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);
        List hosts = new ArrayList();
        serviceInstances.forEach(serviceInstance -> {
            hosts.add(serviceInstance.getUri());
        });
        return hosts;
    }

}