SpringBoot上传文件实现

SpringBoot上传文件实现前言上传文件需求也是日常开发必不可少的操作,今天就稍微总结下,一般如果是上传图片操作,很多稍微大点的公司都有专门的图片服务器可直接将图片上传至那边即可,如果没有图片服务器的话,那么此处把图片也一并归为文件进行讲解。本文代码以springBoot为准上传到哪?这个问题想必我们在实现需求时也必定会思考,那么如果能确定该项目是一个单服务器结构,那为了方便起见,可采用上传至本地服务器的项…

大家好,又见面了,我是你们的朋友全栈君。

前言

上传文件需求也是日常开发必不可少的操作,今天就稍微总结下,一般如果是上传图片操作,很多稍微大点的公司都有专门的图片服务器可直接将图片上传至那边即可,如果没有图片服务器的话,那么此处把图片也一并归为文件进行讲解。本文代码以springBoot为准

 

上传到哪?

这个问题想必我们在实现需求时也必定会思考,那么如果能确定该项目是一个单服务器结构,那为了方便起见,可采用上传至本地服务器的项目中,如果是分布式环境并且有些文件还挺大,这里建议使用mongo的子模块GridFS实现。下面就这两种上传剖出代码

1、上传到本地服务器

    @RequestMapping(value = "/application/file/upload", method = RequestMethod.POST)
    public Object uoloadFile(@RequestParam("file") MultipartFile file) {
        return buildMessage(ResultModel.SUCCESS, appService.uoloadFile(file));
    }

controller层主要以MultipartFile接收即可,这里返回给前端的该文件保存后的相对路径,下面看下service层upload的具体实现:

    public String uploadFile(MultipartFile file) throws NotifyException {
        // 首先校验图片格式
        List<String> imageType = Lists.newArrayList("jpg","jpeg", "png", "bmp", "gif");
        // 获取文件名,带后缀
        String originalFilename = file.getOriginalFilename();
        // 获取文件的后缀格式
        String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
        if (imageType.contains(fileSuffix)) {
            // 只有当满足图片格式时才进来,重新赋图片名,防止出现名称重复的情况
            String newFileName = UUIDTypeHandler.createUUID() + originalFilename;
            // 该方法返回的为当前项目的工作目录,即在哪个地方启动的java线程
            String dirPath = System.getProperty("user.dir");
            String path = File.separator + "uploadImg" + File.separator + newFileName;
            File destFile = new File(dirPath + path);
            if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            try {
                file.transferTo(destFile);
                // 将相对路径返回给前端
                return path;
            } catch (IOException e) {
                log.error("upload pic error");
                return null;
            }
        } else {
            // 非法文件
            log.error("the picture's suffix is illegal");
            throw new NotifyException(ExceptionConstants.FILE_UPLOAD_ERROR);
        }
    }

上述代码是以上传图片为例,上传文件同理,只要去掉图片格式验证即可

2、上传到MongoDB

这里采用它的子模块GridFS实现,对应到代码中则是采用GridFsTemplate类来实现,GridFS使用两个集合(collection)存储文件。一个集合是chunks, 用于存储文件内容的二进制数据;一个集合是files,用于存储文件的元数据及扩展数据。当把一个文件存储到GridFS时,如果文件大于chunksize (每个chunk块大小为256KB),会先将文件按照chunk的大小分割成多个chunk块,最终将chunk块的信息存储在fs.chunks集合的多个文档中。然后将文件信息存储在fs.files集合的唯一一份文档中。其中fs.chunks集合中多个文档中的files_id字段对应fs.files集中文档”_id”字段。

读文件时,先根据查询条件在files集合中找到对应的文档,同时得到“_id”字段,再根据“_id”在chunks集合中查询所有“files_id”等于“_id”的文档。最后根据“n”字段顺序读取chunk的“data”字段数据,还原文件。

整合MongoDB:

为了使本文更全面点,那么先讲springBoot如何整合mongo,由于springBoot默认是没有提供配置连接池的属性,即你在application.yaml中的连接配置是不带连接池功能,因此这里我建议采用代码方式进行配置mongo,同时代码中配置能更好的切换不同的数据库以创建不同的MongoDbFactory,先贴pom文件依赖:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>

然后看下代码配置mongodb与springboot整合:

@Service
public class MongoConfig extends AbstractMongoConfiguration {

    @Override
    public MongoClient mongoClient() {
        MongoClient mongoClient = getMongoClient();
        return mongoClient;
    }

    public MongoClient getMongoClient() {
        // MongoDB地址列表
        List<ServerAddress> serverAddresses = new ArrayList<>();
        serverAddresses.add(new ServerAddress("xxxx:27017"));
        // 连接认证
        MongoCredential credential = MongoCredential.createCredential("xxx", "xx", "xxx".toCharArray());
        MongoClientOptions.Builder builder = MongoClientOptions.builder();

        //最大连接数
        builder.connectionsPerHost(10);
        //最小连接数
        builder.minConnectionsPerHost(0);
        //超时时间
        builder.connectTimeout(1000*3);
        // 一个线程成功获取到一个可用数据库之前的最大等待时间
        builder.maxWaitTime(5000);
        //此参数跟connectionsPerHost的乘机为一个线程变为可用的最大阻塞数,超过此乘机数之后的所有线程将及时获取一个异常.eg.connectionsPerHost=10 and threadsAllowedToBlockForConnectionMultiplier=5,最多50个线程等级一个链接,推荐配置为5
        builder.threadsAllowedToBlockForConnectionMultiplier(5);
        //最大空闲时间
        builder.maxConnectionIdleTime(1000*10);
        //设置池连接的最大生命时间。
        builder.maxConnectionLifeTime(1000*10);
        //连接超时时间
        builder.socketTimeout(1000*10);

        MongoClientOptions myOptions = builder.build();
        MongoClient mongoClient = new MongoClient(serverAddresses, credential, myOptions);
        return mongoClient;
    }

    @Override
    protected String getDatabaseName() {
        return "xxxx";
    }

    /**
     * 获取另一个数据库
     * @return
     */
    public String getFilesDataBaseName() {
        return "xxx";
    }

    /**
     * 用于切换不同的数据库
     * @return
     */
    public MongoDbFactory getDbFactory(String dataBaseName) {
        MongoDbFactory dbFactory = null;
        try {
            dbFactory = new SimpleMongoDbFactory(getMongoClient(), dataBaseName);
        } catch (Exception e) {
            log.error("Get mongo client have an error, please check reason...", e.getMessage());
        }
        return dbFactory;
    }

    /**
     * 获取文件存储模块
     * @return
     */
    public GridFsTemplate getGridFS() {
        return new GridFsTemplate(getDbFactory(getFilesDataBaseName()), mongoTemplate.getConverter());
    }

}

为了测试方便,各参数都直接写死了,建议写到配置文件中去(例如disconf),方便更改或扩展,这里需要注意的是继承的getDatabaseName()方法中返回的数据库为mongoTemplate默认使用的库,若需切换到第二个库,请看如下代码

public String upload(MultipartFile file) {
        // 拿到本文的重点类
        GridFsTemplate gridFsTemplate = mongoConfig.getGridFS();
        try {
            InputStream in = file.getInputStream();
            String filename = file.getOriginalFilename();
            String contentType = file.getContentType();
            // 这是扩展属性,供不同的业务需求,日后可根据特地的参数进行查询
            BasicDBObject dbObject = new BasicDBObject("name", "xj");
            dbObject.put("key", "value");
            String fileId = gridFsTemplate.store(in, filename, contentType, dbObject).toString();
            return fileId;
        } catch (IOException e) {
            log.error("transfer in error .");
            return null;
        }
    }

重点即为图上的store()方法,有多个重载方法,可自行选择。

到这里其实还未结束,springboot上传文件默认支持的大小为1mb,因此当你超过这个限制是会报如下错:

SpringBoot上传文件实现

修改文件上传的大小即可,在yaml文件下增加如下配置:

spring:
  servlet:
    multipart:
      #单个数据的大小
      max-file-size: 100MB
      #总数据的大小
      max-request-size: 100MB

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132529.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • PHP之与或非_php字符串运算符

    PHP之与或非_php字符串运算符在程序运算中,数值都是转换成机器码(二进制)再进行加的,而与或非就是建立这这种基础上,以二进制进行运算。与$1$0=0或|1|0=1非~~1=0

    2022年10月11日
  • centos7安装python3.7_安装python教程

    centos7安装python3.7_安装python教程文章目录前言环境&组件说明组件用途说明准备阶段安装步骤详细步骤准备安装安装Python异常处理异常信息原因分析处理方法小技巧前言工作需要,服务器不能连接外网,因此需要离线安装。推荐在线安装,参考。环境&组件说明操作系统:CentOSLinuxrelease7.4.1708(Core)操作系统安装包:CentOS-7-x86_64-Minimal-1708.isoPython版本:3.8.5pip版本:20.1.1virtualenv版本:20.4.2组件用途说

    2022年9月25日
  • Kafka简明教程「建议收藏」

    Kafka简明教程「建议收藏」作者:柳树之www.jianshu.com/p/7b77723d4f96Kafka是啥?用Kafka官方的话来说就是:Kafkaisusedforbuildingreal-timedatapipelinesandstreamingapps.Itishorizontallyscalable,fault-tolerant,wickedfast,an…

    2022年10月17日
  • 详解 误差反向传播算法推导

    详解 误差反向传播算法推导误差反向传播算法误差反向传播算法(backpropagation,简称BP模型)是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络,是目前应用最广泛的神经网络。误差反向传播算法系统的解决了多层神经网络隐含层连接权学习问题,人们把采用这种算法进行误差校正的多层前馈网络称为BP网。BP神经网络具有任意复杂的模式分类能力和…

    2022年6月10日
  • java经典入门教程(java从入门到精通第几版好用)

    刚开始学习java的时候,可能是一头雾水,不知道从何学起,这里跟大家分享一下!(仅仅只供初级学者学习,大佬勿喷)一、初始java1.生活中的程序:从起床到教室上课的过程穿衣打扮》起床》洗漱》出宿舍》》吃早餐》到教室按照特定的顺序去完成某一件事的过程我们叫做生活中的程序2.计算机中的程序:一组有序指令的集合,需要和计算机交流就要使用计算机语言,java就是计算机语言的一种3.java…

    2022年4月16日
  • 【4】进大厂必须掌握的面试题-Java面试-jdbc

    点击上方“全栈程序员社区”,星标公众号 重磅干货,第一时间送达 1.什么是JDBC驱动程序? JDBC驱动程序是使Java应用程序与数据库进行交互的软件组件。JDBC驱动程序有4种…

    2021年6月23日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号