文件上传下载

2023年 10月 5日 105.9k 0

介绍

文件上传,也称为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);  
        }  
    }
    

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论