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

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

A服务(服务提供者)

控制层:

    @ApiOperation("批量文件上传")
    @PostMapping("/uploadFiles")
    //响应的是k:文件名 v:文件存储路径
    public JsonResult> 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 uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        return JsonResultTool.success(fileService.uploadFile(file));
    }

业务层:

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

    @Override
    public Map uploadFiles(MultipartFile[] files) throws IOException {
        if (files == null ||files.length == 0) {
            return null;
        }
        Map 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> uploadFiles(@RequestPart("files") MultipartFile[] files) throws IOException;
 
//备注:以上批次接口我没有测试过,不好判断

    
    //单个文件的调用
    @PostMapping(value = "/filesystem/uploadFile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    JsonResult 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 downloadFileBytes(String path, String fileName) throws IOException {
        return fileService.downloadFileBytes(path, fileName);
    }

//业务层
    @Override
    public ResponseEntity 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(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 downloadFileBytes(@RequestParam("path") String path, @RequestParam("fileName") String fileName) throws IOException;

B调用A:

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

你可能感兴趣的:(Spring,spring,java,mybatis,spring,cloud)