Spring上传和下载以及Feign调用时操作

一、上传文件(以批次为例)

A服务(服务提供者)

控制层:

    @ApiOperation("批量文件上传")
    @PostMapping("/uploadFiles")
    //响应的是k:文件名 v:文件存储路径
    public JsonResult<Map<String,String>> uploadFiles(@RequestParam("files") MultipartFile[] files) throws IOException {
        return JsonResultTool.success(fileService.uploadFiles(files));
    }

    @ApiOperation("单个文件上传")
    @PostMapping(value = "/uploadFile",consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public JsonResult<String> uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        return JsonResultTool.success(fileService.uploadFile(file));
    }

业务层:

    //类常量引用
    @Resource
    MultipartConfigElement config;

    @Override
    public Map<String, String> uploadFiles(MultipartFile[] files) throws IOException {
        if (files == null ||files.length == 0) {
            return null;
        }
        Map<String, String> map = new HashMap<>();
        for (MultipartFile file : files) {
            if (!file.isEmpty()) {
                //获取默认的绝对路径
                String localtion = config.getLocation();
                //创建自定义路径并返回路径字符串        
                String fileDir = FileUploadUtils.uploadFile(localtion, file);
                map.put(file.getOriginalFilename(), fileDir);
            }
        }
        return map;
    }

​
    //可以自己写一个配置类文件或者直接放在启动类(配置的目的还是自己定义绝对路径)
    @Bean
    MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        String osName = System.getProperty("os.name").toLowerCase();
        String path = "";
        if( osName.indexOf(WINDOWS) >= 0){
            path = "d:/data/temp/";
        }else{
            path = "/root/data/temp";
        }
        if(!FileUtil.exist(path)){
            FileUtil.mkdir(path);
        }
        factory.setLocation(path);
        factory.setMaxFileSize(DataSize.parse(maxFileSize));
        factory.setMaxRequestSize(DataSize.parse(maxRequestSize));
        return factory.createMultipartConfig();
    }

​
    /**
     * 根据文件路径上传
     *
     * @param baseDir 相对应用的基目录
     * @param file    上传的文件
     * @return 文件名称
     * @throws IOException
     */
    public static final String uploadFile(String baseDir, MultipartFile file) throws IOException {
        return upload(baseDir, file);
    }

    /**
     * 文件上传
     *
     * @param baseDir   相对应用的基目录
     * @param file      上传的文件
     * @return 返回上传成功的文件名
     * @throws IOException 异常
     */
    public static final String upload(String baseDir, MultipartFile file) throws IOException{

        String fileName = file.getOriginalFilename();
        //校验文件名称长度
        checkFileNameLength(fileName);
        //获取保存的目录路径
        String fileDir = getFileDir(baseDir, fileName);
        //写文件
        file.transferTo(new File(fileDir,fileName));
        return fileDir;
    }

    /**
     * 检查文件名称长度
     * @param fileName 文件名称
     */
    public static final void checkFileNameLength(String fileName) {
        if (fileName.length() > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
            throw new FileException(FileExceptionEnums.FILE_NAME_TOO_LONG);
        }
    }

    /**
     * 生成文件路径
     * */
    private static final String getFileDir(String uploadDir, String fileName) {
        String ext = FileUtil.extName(fileName);
        String datePath = DateUtils.datePath();
        //储存路径
        StringBuilder path = new StringBuilder();
        path.append(uploadDir).append(datePath).append("/").append(ext).append("/");
        //path一定是绝对路径例如d:xxx/xxx或者linux root/xx/xx  否则会提示异常
        File fileDir = new File(path.toString());
        if (!fileDir.exists()){
            fileDir.mkdirs();
        }
        return path.toString();
    }
    

如果无需跨服务调用,到此上传结束!!!!

跨服务调用(消费服务B调用A服务接口):

Feign:

    @PostMapping(value = "/filesystem/uploadFiles",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    JsonResult<Map<String,String>> uploadFiles(@RequestPart("files") MultipartFile[] files) throws IOException;
 
//备注:以上批次接口我没有测试过,不好判断

    
    //单个文件的调用
    @PostMapping(value = "/filesystem/uploadFile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    JsonResult<String> uploadFile(@RequestPart("file") MultipartFile file) throws IOException;

//备注:使用@RequestPart 不要使用@RequestParam
//consumes = MediaType.MULTIPART_FORM_DATA_VALUE 不要忘记

B服务的实现不多介绍

二、下载文件

推荐两种方式:

方式一:java通用下载

服务提供层A:

    @ApiOperation("下载单个文件")
    @GetMapping("/downloadFile")
    public void downloadFile(String path, String fileName, HttpServletResponse response){
        fileService.downloadFile(path, fileName, response);
    }
    @Override
    public void downloadFile(String path,String fileName, HttpServletResponse response) {
        //获取文件
        File file=  getFile(path, fileName);
        if(file == null) {
            throw new FileException(FileExceptionEnums.FILE_NOT_FOUND);
        }

        //1 设置response 响应头
        response.reset();
        response.setCharacterEncoding("UTF-8");
        //2 设置响应文本类型,以xlsx格式为例(可以参考:https://blog.csdn.net/josavion/article/details/115260427)
        response.setContentType("application/octet-stream");
        //fileName我的文件名带后缀的,如果无后缀,这里要补齐"attachment;filename="+ fileName + ".xlsx"
        response.setHeader("Content-Disposition",
                "attachment;filename="+ fileName);
        try {
            //读取文件--输入流
            InputStream input = new FileInputStream(file);
            BufferedInputStream bufferedInputStream = new BufferedInputStream(input);
            //写出文件--输出流
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
            int length = 0;
            byte[] temp = new byte[1024 * 10];
            while ((length = bufferedInputStream.read(temp)) != -1) {
                bufferedOutputStream.write(temp, 0, length);
            }
            bufferedOutputStream.flush();
            bufferedOutputStream.close();
            bufferedInputStream.close();
            input.close();
        } catch (IOException e) {
            log.error("文件:{}下载失败,",fileName,e);
            throw new FileException(FileExceptionEnums.DOWN_LOAD_ERROR);
        }
    }

    private File getFile(String path, String fileName) {
        File file = new File(path + fileName);
        if (!(file.exists() && file.canRead())) {
            return null;
        }
        return file;
    }

Feign:

    @GetMapping("/filesystem/downloadFile")
    //返回的是Response 
    Response downloadFile(@RequestParam("path") String path, @RequestParam("fileName") String fileName);

B调用A:

    @Override
    public void getFile(String path, String fileName, HttpServletResponse response) throws IOException {
        InputStream inputStream = null;
        Response serviceResponse = fileClient.downloadFile(path, fileName);
        //获取body
        Response.Body body = serviceResponse.body();
        //输入流
        inputStream = body.asInputStream();
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        //输出流
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
        int length = 0;
        byte[] temp = new byte[1024 * 10];
        while ((length = bufferedInputStream.read(temp)) != -1) {
            bufferedOutputStream.write(temp, 0, length);
        }
        bufferedOutputStream.flush();
        bufferedOutputStream.close();
        bufferedInputStream.close();
        inputStream.close();
    }

方式二:基于ResponseEntity实现(建议)

A服务:

    @ApiOperation("下载单个文件")
    @GetMapping("/downloadFileBytes")
    public ResponseEntity<byte[]> downloadFileBytes(String path, String fileName) throws IOException {
        return fileService.downloadFileBytes(path, fileName);
    }

//业务层
    @Override
    public ResponseEntity<byte[]> downloadFileBytes(String path, String fileName) throws IOException {
        File file=  getFile(path, fileName);
        if(file == null) {
            throw new FileException(FileExceptionEnums.FILE_NOT_FOUND);
        }
        HttpHeaders headers = new HttpHeaders();
        String filename = new String(fileName.getBytes("utf-8"),"iso-8859-1");
        headers.setContentDispositionFormData("attachment", filename);
        //感兴趣的可以去看一下MediaType
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
    }

    private File getFile(String path, String fileName) {
        File file = new File(path + fileName);
        if (!(file.exists() && file.canRead())) {
            return null;
        }
        return file;
    }

Feign:

@GetMapping("/filesystem/downloadFileBytes")
    ResponseEntity<byte[]> downloadFileBytes(@RequestParam("path") String path, @RequestParam("fileName") String fileName) throws IOException;

B调用A:

    @Override
    public ResponseEntity<byte[]> getFileBytes(String path, String fileName) throws IOException {
        String resourceName = report.getFileName();
        ResponseEntity<byte[]> data = fileClient.downloadFileBytes(path,fileName);
        return data;
    }

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Cloud微服务架构中,Nacos是一个注册中心和配置中心。Feign是一个声明式的Web服务客户端,它使得编写Web服务客户端变得更加容易。 使用Feign调用接口需要以下步骤: 1. 在pom.xml中添加Feign依赖 ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> ``` 2. 在启动类上添加@EnableFeignClients注解启用Feign客户端 ```java @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 3. 创建接口,并使用@FeignClient注解指定调用的服务名称和服务路径 ```java @FeignClient(name = "service-provider") public interface UserService { @GetMapping("/user/{id}") String getUserById(@PathVariable("id") Long id); } ``` 其中,name属性指定服务名称,GetMapping注解指定服务路径。 4. 在需要使用该服务的地方注入UserService并调用方法即可 ```java @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/user/{id}") public String getUserById(@PathVariable("id") Long id) { return userService.getUserById(id); } } ``` 在这个例子中,我们定义了一个名为UserService的Feign客户端,指定了调用的服务名称和服务路径。然后在UserController中注入了UserService并调用了其方法。最终,Feign会自动将该请求转发到名为service-provider的微服务,并返回结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值