文件上传下载

介绍

文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。

文件上传时,对页面的form表单有如下要求:

  • method="post" 采用post方式提交数据

  • enctype="multipart/form-data!采用multipart格式上传文件type="file"

  • 使用input的file控件上传

  • 举例:

    核心代码

    package com.example.demo.controller;
    import cn.dev33.satoken.annotation.SaCheckLogin;
    import com.example.demo.common.Result;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.UUID;
    @Slf4j
    @RestController
    @RequestMapping("/common")
    public class CommonController {
    @Value("${takeOutFile.fileLocaltion}")
    private String basePath ;
    @PostMapping("/upload")
    public Result upload(MultipartFile file){
    //这里的file只是一个临时的文件存储,临时存储到某一个位置,然后待接收完毕后再转存到目标位置上,然后再把这个临时文件删除
    //截取文件后缀
    String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
    //生成UUID
    String randomUUID = UUID.randomUUID().toString();
    //拼接文件最后名称,结果为文件本体名字+UUID+后缀
    String fileName = file.getOriginalFilename() + randomUUID + suffix;
    //保证存储的位置有这个文件夹
    File dir = new File(basePath);
    if (!dir.exists()) {
    //目标存储位置不存在,就创建一个文件夹
    dir.mkdirs();
    }
    try {
    //转存文件到指定位置+文件的名称全拼
    file.transferTo(new File(basePath+fileName));
    } catch (IOException e) {
    e.printStackTrace();
    }
    //把文件的名字上传回去,方便后续回显读取路径
    return Result.success(fileName);
    }
    /**
    * 文件回显接口
    * @param httpServletResponse 响应对象
    * @param name 上传的文件名称
    * @throws IOException IO异常
    */
    @GetMapping("/download")
    public void fileDownload(HttpServletResponse httpServletResponse, String name) throws IOException {
    //把刚刚存的文件读取到内存中,准备回显
    FileInputStream fileInputStream = new FileInputStream(new File(basePath+name));
    log.info("文件存储的位置为:"+basePath+name);
    //把读取到内存中的图片用输出流写入Servlet响应对象里
    ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
    //可选项,选择响应类型
    httpServletResponse.setContentType("image/jpeg");
    //用byte数组写入,注意是小写b,不是大写,大写就是包装类了
    byte[] fileArray = new byte[1024];
    int length=0;
    try {
    //只要没读到数组的尾部就一直读下去,这部分是IO的内容
    while ((length=fileInputStream.read(fileArray))!=-1) {
    //写入响应流,从0开始,写入到数组末尾长度
    servletOutputStream.write(fileArray, 0, length);
    //把流里的东西挤出来
    servletOutputStream.flush();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }finally {
    //关闭流
    fileInputStream.close();
    servletOutputStream.close();
    }
    return;
    }
    }

    使用阿里云上传文件

    添加application.yml配置

    sky:
    alioss:
    endpoint: ${sky.alioss.endpoint}
    access-key-id: ${sky.alioss.access-key-id}
    access-key-secret: ${sky.alioss.access-key-secret}
    bucket-name: ${sky.alioss.bucket-name}

    创建工具类

    @Data
    @AllArgsConstructor
    @Slf4j
    public class AliOssUtil {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    /**
    * 文件上传
    *
    * @param bytes
    * @param objectName
    * @return
    */
    public String upload(byte[] bytes, String objectName) {
    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    try {
    // 创建PutObject请求。
    ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
    } catch (OSSException oe) {
    System.out.println("Caught an OSSException, which means your request made it to OSS, "
    + "but was rejected with an error response for some reason.");
    System.out.println("Error Message:" + oe.getErrorMessage());
    System.out.println("Error Code:" + oe.getErrorCode());
    System.out.println("Request ID:" + oe.getRequestId());
    System.out.println("Host ID:" + oe.getHostId());
    } catch (ClientException ce) {
    System.out.println("Caught an ClientException, which means the client encountered "
    + "a serious internal problem while trying to communicate with OSS, "
    + "such as not being able to access the network.");
    System.out.println("Error Message:" + ce.getMessage());
    } finally {
    if (ossClient != null) {
    ossClient.shutdown();
    }
    }
    //文件访问路径规则 https://BucketName.Endpoint/ObjectName
    StringBuilder stringBuilder = new StringBuilder("https://");
    stringBuilder
    .append(bucketName)
    .append(".")
    .append(endpoint)
    .append("/")
    .append(objectName);
    log.info("文件上传到:{}", stringBuilder.toString());
    return stringBuilder.toString();
    }
    }

    注入实体类

    @Component
    @ConfigurationProperties(prefix = "sky.alioss")
    @Data
    public class AliOssProperties {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    }

    注入工具类

    /**
    * 配置类,用于创建AliOssUtil对象
    */
    @Configuration
    @Slf4j
    public class OssConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
    log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);
    return new AliOssUtil(aliOssProperties.getEndpoint(),
    aliOssProperties.getAccessKeyId(),
    aliOssProperties.getAccessKeySecret(),
    aliOssProperties.getBucketName());
    }
    }

    使用工具类

    /**
    * 通用接口
    */
    @RestController
    @RequestMapping("/admin/common")
    @Api(tags = "通用接口")
    @Slf4j
    public class CommonController {
    @Autowired
    private AliOssUtil aliOssUtil;
    /**
    * 文件上传
    * @param file
    * @return
    */
    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result upload(MultipartFile file){
    log.info("文件上传:{}",file);
    try {
    //原始文件名
    String originalFilename = file.getOriginalFilename();
    //截取原始文件名的后缀 dfdfdf.png
    String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
    //构造新文件名称
    String objectName = UUID.randomUUID().toString() + extension;
    //文件的请求路径
    String filePath = aliOssUtil.upload(file.getBytes(), objectName);
    return Result.success(filePath);
    } catch (IOException e) {
    log.error("文件上传失败:{}", e);
    }
    return Result.error(MessageConstant.UPLOAD_FAILED);
    }
    }