文件上传下载

介绍

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

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

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

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

  3. 使用input的file控件上传

举例:

ini 复制代码
<form method="post" action="/common/upload" enctype="multipart/form-data">
    <input name="myFile" type="file"/>
    <input type="submit"value="提交"/>
</form>

核心代码

java 复制代码
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<String> 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配置

yaml 复制代码
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}

创建工具类

typescript 复制代码
@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();  
    }  
}

注入实体类

less 复制代码
@Component  
@ConfigurationProperties(prefix = "sky.alioss")  
@Data  
public class AliOssProperties {  

    private String endpoint;  
    private String accessKeyId;  
    private String accessKeySecret;  
    private String bucketName;  
  
}

注入工具类

less 复制代码
/**  
* 配置类,用于创建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());  
    }  
}

使用工具类

less 复制代码
/**  
* 通用接口  
*/  
@RestController  
@RequestMapping("/admin/common")  
@Api(tags = "通用接口")  
@Slf4j  
public class CommonController {  

    @Autowired  
    private AliOssUtil aliOssUtil;  

    /**  
    * 文件上传  
    * @param file  
    * @return  
    */  
    @PostMapping("/upload")  
    @ApiOperation("文件上传")  
    public Result<String> 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);  
    }  
}
相关推荐
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
Yaml42 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
小码编匠3 小时前
一款 C# 编写的神经网络计算图框架
后端·神经网络·c#
AskHarries3 小时前
Java字节码增强库ByteBuddy
java·后端
佳佳_3 小时前
Spring Boot 应用启动时打印配置类信息
spring boot·后端
许野平5 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
BiteCode_咬一口代码6 小时前
信息泄露!默认密码的危害,记一次网络安全研究
后端
齐 飞6 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb