【springboot】实现文件上传和下载

1. 新建一个springboot项目

      新建一个springboot项目,选择web,默认即可.

      主要pom配置文件如下:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--web包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
<!--    maven打包设置-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

2. 配置文件

      在配置文件中配置文件上传和下载的根目录,文件大小限制等。

application.properties

file.upload.url=path/to/upload
# 文件大小限制
spring.servlet.multipart.max-file-size=10MB 
# 请求大小限制
spring.servlet.multipart.max-request-size=20MB

application.yml

file.upload.url: path/to/upload
spring:
  servlet:
    multipart:
      # 文件大小限制
      max-file-size: 10MB
      
      max-request-size: 20MB

3. 控制类实现文件上传和下载

      在控制类中实现文件上传和下载。其中,文件上传通过MultipartFile实现文件类型限制、文件大小限制、多文件上传等,下载通过文件流实现。

      新增图片预览方法。

@RestController
@RequestMapping(value = "/file")
@CrossOrigin // 允许跨域
@ControllerAdvice // 全局异常处理
public class FileController {

    //上传的根目录
    @Value("${file.upload.url}")
    private String uploadFilePath;
    @Value("${file.upload.url}")
    private String downloadFilePath;

    //捕获上传文件过大的异常
    //@ExceptionHandler标识方法将处理指定类型的异常
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<String> handleMaxSizeException(MaxUploadSizeExceededException exc) {
        return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE).body("文件过大,请重新选择上传图片!");
    }
    
    @RequestMapping("/upload")
    public String httpUpload(
            @RequestParam("files")
                     //MultipartFile 是 Spring 框架中用于处理文件上传的接口
                     MultipartFile files[]) {
        StringBuffer urls = new StringBuffer();
        //遍历多个文件
        for (int i = 0; i < files.length; i++) {
            //获取文件类型
            String contentType = files[i].getContentType();
            System.out.println(contentType);
            if (!contentType.contains("image")) {
                return "文件格式不正确,请重新选择图片!";
            }
            //获取上传文件的后缀名
            String postfix = files[i].getOriginalFilename().substring(files[i].getOriginalFilename().lastIndexOf("."));
            //生成文件名 使用时间戳,避免重名
            String fileName = System.currentTimeMillis()+postfix;
            System.out.println(fileName);
//            File dest = new File(uploadFilePath + '/' + fileName);
            File dest = new File(uploadFilePath + '/' + fileName);
            //目录不存在则创建目录
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                //将上传的文件保存到指定的目标位置
                files[i].transferTo(dest);
            } catch (Exception e) {
                return "程序错误,请重新上传\n" + e.toString();
            }
            urls.append("\n"+uploadFilePath + '\\' + fileName);
        }
        return "文件上传成功" + urls.toString();
    }

    @RequestMapping("/download")
    public String fileDownLoad(HttpServletResponse response, @RequestParam("fileName") String fileName) {
//        File file = new File(downloadFilePath + '/' + fileName);
        File file = new File(downloadFilePath + '\\' + fileName);
        if (!file.exists()) {
            return "下载文件不存在";
        }
        //清除之前设置的内容
        response.reset();
        //设置响应内容类型为二进制流
        response.setContentType("application/octet-stream");
        //设置响应字符编码为UTF-8
        response.setCharacterEncoding("utf-8");
        //设置响应文件大小
        response.setContentLength((int) file.length());
        //设置浏览器以附件的形式下载,并设置文件名
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
            byte[] buff = new byte[1024];
            OutputStream os = response.getOutputStream();
            int i = 0;
            while ((i = bis.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            return "下载失败";
        }
        return "下载成功";
    }
    /**
     * 图片预览功能接口
     * @param fileName
     * @return
     */
    @RequestMapping("showImage")
    public ResponseEntity<Resource> showImage(@RequestParam("fileName") String fileName) {
        try {
            // 指定图片文件的路径         指定目录            追加文件名到 路径    规范化路径,去除冗余路径元素
            Path filePath = Paths.get(downloadFilePath).resolve(fileName).normalize();
            // 创建一个 Resource 对象,用于封装图片文件的位置
            //                                   将 Path 对象转换为 URI 对象
            Resource resource = new UrlResource(filePath.toUri());

            // 检查文件是否存在且可读
            if (resource.exists() && resource.isReadable()) {
                // 根据文件扩展名设置 Content-Type
                String contentType;
                if (fileName.endsWith(".png")) {
                    contentType = "image/png";
                } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
                    contentType = "image/jpeg";
                } else if (fileName.endsWith(".gif")) {
                    contentType = "image/gif";
                } else {
                    // 如果不是图片类型,返回错误响应
                    return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
                            .body(null);
                }
                return ResponseEntity.ok()
                        // 设置响应头,告诉浏览器如何处理文件
                        // Content-Disposition: inline 表示在浏览器中直接显示图片 同时fileName指定文件名
                        .header(HttpHeaders.CONTENT_DISPOSITION, "inline;filename=\"" + fileName + "\"")
                        .header(HttpHeaders.CONTENT_TYPE, contentType)
                        .body(resource);
            } else {
                //创建一个 404 错误响应
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            // 创建一个 500 错误响应
            return ResponseEntity.status(500).build();
        }
    }
}

4. 测试

      以下测试使用工具postman实现。测试文件大小的图片可以使用代码生成,可参考文章

      测试文件上传格式限制。
在这里插入图片描述

      测试文件上传图片大小限制。

在这里插入图片描述
      测试文件上传正常上传图片。

在这里插入图片描述
      测试文件下载。

在这里插入图片描述

      测试文件预览。

在这里插入图片描述

5. 在其他控制器中调用接口

      通过在其他控制器中调用接口,实现文件上传和下载。

      1. 配置类

      RestTemplate是Spring框架提供的一个同步客户端,用于简化与RESTful Web服务的交互。可以用来发送HTTP请求和处理HTTP响应,支持GET、POST、PUT、DELETE等常见的HTTP方法,可以发送带有请求头、请求体的复杂请求;自动将响应体转换为Java对象,支持处理不同的响应状态码和异常。

@Configuration
@ComponentScan
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

      2. 使用RestTemplate在控制类中调用接口

@RestController
@RequestMapping("test")
public class TestController {
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 测试调用接口
     */
    @PostMapping("callingInterface")
    public ResponseEntity<String> addResfood(@RequestParam("files") MultipartFile files) throws IOException {
        String url = "http://example.com/uploadFiles"; // 替换为实际的文件上传接口URL
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        // 设置请求头,指定为 multipart/form-data 允许在一个请求中上传多个文件和其他表单字段。
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        // 创建请求体,将文件添加到请求中
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        // 将文件添加到请求中
        body.add("files", new FileSystemResource(convert(files)));

        // 创建请求实体,将请求头和请求体关联
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
        // 发送 POST 请求
        ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);

        return response;
    }
    // 将 MultipartFile 转换为 File
    private File convert(MultipartFile file) throws IOException {
        // 创建临时文件            获取文件名称
        File convFile = new File(file.getOriginalFilename());
        // 将 MultipartFile 写入临时文件
        try (FileOutputStream fos = new FileOutputStream(convFile)) {
            fos.write(file.getBytes());
        }
        return convFile;
    }
}

      3. 测试

在这里插入图片描述


参考链接:

https://cloud.tencent.com/developer/article/1594124

https://cloud.baidu.com/article/2773207

https://blog.csdn.net/m0_63297090?type=blog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睆小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值