栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot文件服务器 一(IO流+微服务包含swagger、出入参统一格式、log4j2日志)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot文件服务器 一(IO流+微服务包含swagger、出入参统一格式、log4j2日志)

一、背景说明

文件、图片上传下载是一个非常常用的功能。微服务也是一个轻量级应用。将二者融合,把文件的上传下载功能做成微服务,使此功能独立于业务功能代码之外。可以方便切换与不同的项目之间,使上传下载功能和其他应用实现解耦合的同时,更方便与我们的管理。

二、方案说明

第一套方案为:微服务 + IO流自己定义上传下载功能

优点:配置需要简单,搭建容易,只需要一台大容量服务器即可实现功能,不需要nginx。全程用流处理文件,代码量较多。

项目使用spring cloud alibaba微服务  nacos做配置中心  feign+Ribbon做远程调用代理 sentinel做熔断处理。微服务使用版本spring cloud alibaba 版本 2021.1  ==> Spring Boot 版本 2.4.2 ==> Spring Cloud版本 2020.0.2

微服务接口按照统一出参入参格式管理

微服务接口按照swagger对外提供接口

第二套方案:微服务 + fastdfs 

优点:fastdfs 是一个比较成熟的分布式做文件服务器的一个应用。使用起来比较简单,代码量少,需要配置条件较多 需要配置Nginx+FastDfs+微服务。

本文先使用第一种方案

三、环境配置管理

前提准备:

1、需要部署Nacos

2、准备一台Linux服务器即可

四、代码管理

主要代码量为 文件服务器: 微服务+IO流

应用方:微服务

其中IO流方案,具体描述已在博客中详细写过,本文主要介绍一下微服务之间的调用关系。少量篇幅来介绍IO流上传下载。参考:(7条消息) springboot文件上传与下载_无敌小田田的博客-CSDN博客https://blog.csdn.net/qq_36602951/article/details/119452787

1、新建gradle 的spring boot项目:filemanage 项目名称

代码路径如下:

build.gradle文件

plugins {
    id 'org.springframework.boot' version '2.4.2'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}

group 'com.cicccrm'
version '1.0.0'

repositories {
    mavenCentral()
    maven { url 'http://nexus.cicconline.com/repository/maven-public'}
    maven { url 'https://repo.spring.io/milestone' }
    maven { url 'https://repo.spring.io/snapshot' }
}
ext {
    springCloudVersion = "2020.0.2"
    springBootVersion = "2.4.2"
    comAlibabaCloud = "2021.1"
}
configurations {
    all*.exclude module:'spring-boot-starter-logging'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compile("org.springframework.boot:spring-boot-starter")
            {
                exclude module: 'org.springframework.boot:spring-boot-starter-logging'
            }
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation group: 'com.alibaba.boot', name: 'nacos-config-spring-boot-starter', version: '0.2.1'
    compile group: 'io.springfox', name: 'springfox-swagger2', version: '3.0.0'
    compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '3.0.0'
    implementation group: 'com.alibaba.cloud', name: 'spring-cloud-starter-alibaba-nacos-discovery', version: '2021.1'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-log4j2'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
    testCompile group: 'junit', name: 'junit', version: '4.12'
    implementation group: 'org.springframework.session', name: 'spring-session-core', version: '2.4.2'
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
    implementation group: 'com.alibaba', name: 'fastjson', version: '1.2.41'

}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
    }
}
test {
    useJUnitPlatform()
}

2、application.properties配置文件

server.port=8088
webRoot=http://localhost:8088
spring.application.name=fengqx-fileManager
#nacos地址
spring.cloud.nacos.discovery.server-addr=1.2.3.4:8848
#nacos命名空间
spring.cloud.nacos.discovery.namespace=*******
#nacos默认组
spring.cloud.nacos.discovery.group=DEFAULT_GROUP
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoints.health.show-details=always
#日志管理log4j2
logging.config=classpath:log4j2.xml
#文件保存路径 jar所在路径+/oneRoomFile
file.save.path=filePath
#文件上传大小配置
spring.servlet.multipart.max-file-size = 5MB
spring.servlet.multipart.max-request-size = 50MB

3、Main 函数 FileApplication.java

package com.*****.fileManage;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;


@SpringBootApplication
@EnableDiscoveryClient
public class FileApplication {

    public static void main(String[] args) {
        SpringApplication.run(FileApplication.class, args);
    }

}

4、gradle中还设置了swagger,需要增加swagger的配置文件

com.***.fileManage.annotation下 ApiVersion.java 接口

package com.****.fileManage.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApiVersion {

    
    String[] value();
}

com.****.fileManage.config下 ApiVersionConstant.java接口

package com.*****.fileManage.config;
public interface ApiVersionConstant {
    
    String ONE_CRM_SPRINT_10 = "v-sprint10";
    String ONE_CRM_SPRINT_11 = "v-sprint11";
}

com.****.fileManage.config下 SwaggerConfig.java配置类

package com.****.fileManage.config;



import com.****.fileManage.annotation.ApiVersion;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.documentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.UiConfiguration;
import springfox.documentation.swagger.web.UiConfigurationBuilder;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.lang.reflect.Field;
import java.util.Arrays;


@Configuration
@EnableSwagger2
@EnableWebMvc
public class SwaggerConfig extends WebMvcConfigurerAdapter implements InitializingBean {

    @Autowired
    private ApplicationContext applicationContext;

   // @Value("${swagger.remark}")
    //private String swaggerRemark;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.
                addResourceHandler("/swagger-ui
    @Bean
    public Docket createRestApi() {
        return new Docket(documentationType.SWAGGER_2)
                .groupName("CrmApi")
                .genericModelSubstitutes(DeferredResult.class)
//                .genericModelSubstitutes(ResponseEntity.class)
                .useDefaultResponseMessages(false)
                .forCodeGeneration(true)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.cicccrm.fileManage.controller"))
                .paths(PathSelectors.any())
                .build()
                .apiInfo(apiInfo());
        //com.cicc.gwms.dataSummary,
    }


    private Docket buildDocket(String groupName) {
        return new Docket(documentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName(groupName)
                .select()
                .apis(method -> {
                    // 每个方法会进入这里进行判断并归类到不同分组,**请不要调换下面两段代码的顺序,在方法上的注解有优先级**
                    // 该方法上标注了版本
                    if (method.isAnnotatedWith(ApiVersion.class)) {
                        ApiVersion apiVersion = method.getHandlerMethod().getMethodAnnotation(ApiVersion.class);
                        if (apiVersion.value() != null && apiVersion.value().length != 0) {
                            if (Arrays.asList(apiVersion.value()).contains(groupName)) {
                                return true;
                            }
                        }

                    }
                    // 方法所在的类是否标注了?
                    ApiVersion annotationOnClass = method.getHandlerMethod().getBeanType().getAnnotation(ApiVersion.class);
                    if (annotationOnClass != null) {
                        if (annotationOnClass.value() != null && annotationOnClass.value().length != 0) {
                            if (Arrays.asList(annotationOnClass.value()).contains(groupName)) {
                                return true;
                            }
                        }
                    }
                    return false;
                })
                .paths(PathSelectors.any())
                .build();
    }


    //    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("调用服务接口")
               // .description(swaggerRemark)
                .termsOfServiceUrl(webRoot + "/v2/api-docs")
                .version("1.0")
                .build();
    }

    
    @Bean
    public UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder()
                .displayRequestDuration(true)
                .validatorUrl("")
                .build();
    }

    

    @Override
    public void afterPropertiesSet() throws Exception {
        // ApiConstantVersion 里面定义的每个变量会成为一个docket
        Class clazz = ApiVersionConstant.class;
        Field[] declaredFields = clazz.getDeclaredFields();

        // 动态注入bean
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        if (autowireCapableBeanFactory instanceof DefaultListableBeanFactory) {
            DefaultListableBeanFactory capableBeanFactory = (DefaultListableBeanFactory) autowireCapableBeanFactory;
            for (Field declaredField : declaredFields) {

                // 要注意 "工厂名和方法名",意思是用这个bean的指定方法创建docket
                AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                        .genericBeanDefinition()
                        .setFactoryMethodonBean("buildDocket", "swaggerConfig")
                        .addConstructorArgValue(declaredField.get(ApiVersionConstant.class)).getBeanDefinition();
                capableBeanFactory.registerBeanDefinition(declaredField.getName(), beanDefinition);
            }
        }
    }

}

com.****.fileManage.config下WebConfig.java文件

package com.****.fileManage.config;


import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    // 增加映射关系
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/index").setViewName("redirect:/swagger-ui/index.html");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("
public class ApibaseMessage {

    boolean success;
    String statusCode = "";
    T data;
    String error = "";

    public ApibaseMessage() {}

    public ApibaseMessage(T data) {
        this.success = true;

        this.data = data;
    }

    public static com.****.fileManage.common.model.ApibaseMessage getOperationSucceedInstance(Object data)
    {
        return getSucceedInstance("30001", data);
    }

    public static com.****.fileManage.common.model.ApibaseMessage getOperationFailedInstance()
    {
        return getFailedInstance("30002");
    }

    public static com.****.fileManage.common.model.ApibaseMessage getSucceedInstance(String statusCode, Object data)
    {
        com.****.fileManage.common.model.ApibaseMessage instance = new com.****.fileManage.common.model.ApibaseMessage(statusCode, data);
        instance.setSuccess(true);
        return instance;
    }

    public static com.****.fileManage.common.model.ApibaseMessage getFailedInstance(String statusCode, Object data)
    {
        com.****.fileManage.common.model.ApibaseMessage instance = new com.****.fileManage.common.model.ApibaseMessage(statusCode, data);
        instance.setSuccess(false);
        return instance;
    }

    public static com.****.fileManage.common.model.ApibaseMessage getFailedInstance(String statusCode)
    {
        com.****.fileManage.common.model.ApibaseMessage instance = new com.****.fileManage.common.model.ApibaseMessage(statusCode);
        instance.setSuccess(false);
        instance.setData("");
        return instance;
    }

    public ApibaseMessage(String statusCode, T data) {
        this.statusCode = statusCode;
        this.error = ApiStatusCodeList.getMessage(statusCode);
        this.data = data;
    }

    public ApibaseMessage(String statusCode) {
        this.statusCode = statusCode;
        this.error = ApiStatusCodeList.getMessage(statusCode);
    }

    public ApibaseMessage(String statusCode, String error) {
        this.statusCode = statusCode;
        this.error = error;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(String statusCode) {
        this.statusCode = statusCode;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }
}

 com.****.fileManage.common.model中的 ApiStatusCodeList.java

package com.****.fileManage.common.model;

import java.util.HashMap;
import java.util.Locale;


public class ApiStatusCodeList {

    private static HashMap codeMap = null;

    private static final String[][] CODE_ARRAY = {
            // 账号
            {"10001", "账号输入为空", "The account is not presented."},
            {"10002", "用户名或密码错误", ""},
            {"10003", "登录失败", ""},
            {"10004", "用户账号不存在", ""},
            {"10005", "用户账号状态异常", ""},
            {"10006", "账号已冻结", ""},
            {"10007", "非IC账号", ""},
            {"10008", "账号已登出", ""},
            {"10009", "不能进行该操作", ""},
            {"10010", "当前登录设备与系统记录不符,请联系管理员", ""},
            {"10020", "您目前还没有资产配置建议", ""},
            {"20001","文件不存在", ""},
            {"20002","下载文件失败", ""},
            //操作成功
            {"30001", "操作成功", ""},
            {"30002", "操作失败", ""},
            // 安全
            {"70001", "验证码不正确", ""},
            // 来自app服务的错误
            {"90001", "服务端错误", ""},
            {"90002", "权限错误", ""},
            {"90003", "您尚未拥有该操作权限", ""}
    };

    public static String getMessage(String code) {
        HashMap codeMapInstance = getCodeMapInstance();
        CodeMessage codeMessage = codeMapInstance.get(code);
        return codeMessage.getZhCn();
    }

    public static String getMessage(String code, Locale locale){
        HashMap codeMapInstance = getCodeMapInstance();
        CodeMessage codeMessage = codeMapInstance.get(code);

        switch(locale.toString()){
            case "en":
                return codeMessage.getEn();
            default:
                return codeMessage.getZhCn();
        }
    }

    private static HashMap getCodeMapInstance(){
        if(codeMap == null){
            codeMap = genCodeMap();
        }
        return codeMap;
    }

    private static HashMap genCodeMap(){
        codeMap = new HashMap<>();

        for (String[] aCodeArray : CODE_ARRAY) {
            CodeMessage m = new CodeMessage();
            m.setStatusCode(aCodeArray[0]);
            // zh-cn is the first (1).
            m.setZhCn(aCodeArray[1]);
            m.setEn(aCodeArray[2]);
            codeMap.put(aCodeArray[0], m);
        }

        return codeMap;
    }

    public static class CodeMessage {

        private String statusCode;
        private String zhCn;
        private String zhTw;
        private String en;

        public String getZhCn() {
            return zhCn;
        }

        public void setZhCn(String zhCn) {
            this.zhCn = zhCn;
        }

        public String getZhTw() {
            return zhTw;
        }

        public void setZhTw(String zhTw) {
            this.zhTw = zhTw;
        }

        public String getEn() {
            return en;
        }

        public void setEn(String en) {
            this.en = en;
        }

        public String getStatusCode() {
            return statusCode;
        }

        public void setStatusCode(String statusCode) {
            this.statusCode = statusCode;
        }
    }
}

com.****.fileManage.common.model中的JsonResult.java

package com.****.fileManage.common.model;

public class JsonResult {

    private int code;
    private String msg;
    private Object data;

    public JsonResult() {
    }

    public JsonResult(int code, String msg, T data){
        this.code=code;
        this.data=data;
        this.msg=msg;
    }

    public static com.****.fileManage.common.model.JsonResult jsonErrorMsg (int code, String msg){
        return new com.****.fileManage.common.model.JsonResult(code,msg);
    }

    public static com.****.fileManage.common.model.JsonResult jsonSuccessMsg (int code, String msg, Object data){
        return new com.****.fileManage.common.model.JsonResult(code,msg,data);
    }
    public static com.****.fileManage.common.model.JsonResult jsonSuccessMsg (int code, String msg){
        return new com.****.fileManage.common.model.JsonResult(code,msg);
    }
    public JsonResult(int code, String msg){
        this.code = code;
        this.msg  = msg;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

后续出参,使用 ApibaseMessage 实体就可以统一出参了。

 6、文件上传下载接口

com.****.fileManage.common.model 中的 FilePath.java 文件

package com.****.fileManage.common.model;

import io.swagger.annotations.ApiModelProperty;


public class FilePath {
    @ApiModelProperty(value = "id")
    private String id;
    @ApiModelProperty(value = "文件分类")
    private String fileType;
    @ApiModelProperty(value = "文件名")
    private String fileName;
    @ApiModelProperty(value = "文件路径")
    private String filePath;
    @ApiModelProperty(value = "依赖id")
    private String relyId;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFileType() {
        return fileType;
    }

    public void setFileType(String fileType) {
        this.fileType = fileType;
    }

    public String getRelyId() {
        return relyId;
    }

    public void setRelyId(String relyId) {
        this.relyId = relyId;
    }

    @Override
    public String toString() {
        return "FilePath{" +
                "id='" + id + ''' +
                ", fileType='" + fileType + ''' +
                ", fileName='" + fileName + ''' +
                ", filePath='" + filePath + ''' +
                ", relyId='" + relyId + ''' +
                '}';
    }
}

com.****.fileManage.util中的 FileUtils.java 

package com.****.fileManage.common.util;

import com.****.fileManage.common.model.FilePath;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;



public class FileUtils {
    private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(FileUtils.class);

    
    public static Builder setPathName(String pathName) {
        return builder().setPathName(pathName);
    }

    
    public static Builder setMaxSize(int maxSize) {
        return builder().setMaxSize(maxSize);
    }

    
    public static Builder setMaxFileNameLength(int maxFileNameLength) {
        return builder().setMaxFileNameLength(maxFileNameLength);
    }

    
    public static Builder setAllowedExtension(String[] allowedExtension) {
        return builder().setAllowedExtension(allowedExtension);
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        
        private long defaultMaxSize = 5 * 1024 * 1024;
        
        private int defaultFileNameLength = 100;
        
        private String[] defaultAllowedExtension = {"pdf", "xlsx", "xls", "docx", "doc", "ppt", "pptx"
                ,"jpg","jpeg","png","gif","bmp"};
        
        private String pathName;

        public Builder setMaxSize(int maxSize) {
            this.defaultMaxSize = (long) maxSize * 1024 * 1024;
            return this;
        }

        public Builder setMaxFileNameLength(int maxFileNameLength) {
            this.defaultFileNameLength = maxFileNameLength;
            return this;
        }

        public Builder setAllowedExtension(String[] allowedExtension) {
            this.defaultAllowedExtension = allowedExtension;
            return this;
        }

        public Builder setPathName(String pathName) {
            this.pathName = pathName;
            return this;
        }

        
        public final FilePath upload(MultipartFile file) throws Exception {
            //校验
            if (StringUtils.trimTonull(pathName) == null) {
                throw new IOException("文件保存路径为空");
            }
            String extensionFilename = FilenameUtils.getExtension(file.getOriginalFilename());
            if (!ArrayUtils.isEmpty(defaultAllowedExtension) && !ArrayUtils.contains(defaultAllowedExtension, extensionFilename)) {
                throw new IOException("只允许" + ArrayUtils.toString(defaultAllowedExtension) + "文件上传");
            }
            if (file.getSize() > defaultMaxSize) {
                throw new IOException("文件过大");
            }
            if (file.getOriginalFilename().length() > defaultFileNameLength) {
                throw new IOException("文件名过长");
            }
            //上传
            String fileName = extractFilename(file);
            File desc = getAbsoluteFile(pathName, fileName);
            try {
                file.transferTo(desc);
            } catch (IllegalStateException e) {
                LOG.error("文件上传出现错误" + e.getLocalizedMessage());
                e.printStackTrace();
                throw e;
            } catch (IOException e) {
                LOG.error("文件上传出现错误" + e.getLocalizedMessage());
                e.printStackTrace();
                throw e;
            }
            FilePath filePath = new FilePath();
            filePath.setFileName(file.getOriginalFilename());
            filePath.setFilePath(pathName + File.separator + fileName);
            return filePath;
        }

        
        private final String extractFilename(MultipartFile file) {
            String filename = file.getOriginalFilename();
//            String extension = getExtension(file);
            filename = DateFormatUtils.format(new Date(), "yyyy-MM-dd") + File.separator + getFinalFileName(file);
            return filename;
        }

        
//        private final String encodingFilename(String filename) {
//            filename = filename.replace("_", " ");
//            filename = DigestUtils.md5Hex(filename + System.nanoTime() + RandomStringUtils.randomNumeric(6));
//            return filename;
//        }

        
        public final String getExtension(MultipartFile file) {
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            return extension;
        }

        
        public String getFinalFileName(MultipartFile file) {
            //获取后缀
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            //获取前缀
            String removeExtension = FilenameUtils.removeExtension(file.getOriginalFilename());
            //获取随机字符串+时间戳
            String extra = UUID.randomUUID().toString().replaceAll("-", "");
            return removeExtension + extra + "." + extension;
        }

        
        private final File getAbsoluteFile(String uploadDir, String filename) throws IOException {
            try {
                //获取jar根路径
                ApplicationHome h = new ApplicationHome(getClass());
                File jarF = h.getSource();
                File desc = new File(jarF.getParentFile().toString() + File.separator + uploadDir + File.separator + filename);
                LOG.error("file===" + jarF.getParentFile().toString() + File.separator + uploadDir + File.separator + filename);
                try {
                    if (!desc.getParentFile().exists()) {
                        desc.getParentFile().mkdirs();
                    }
                    if (!desc.exists()) {
                        desc.createNewFile();
                    }
                } catch (Exception e) {
                    LOG.error(e.getMessage());
                    throw e;
                }
                return desc;
            } catch (Exception ex) {
                throw ex;
            }
        }

        
        public static ResponseEntity download( String filePath) throws IOException {
            File file = new File(filePath);//新建一个文件
            HttpHeaders headers = new HttpHeaders();//http头信息
            String downloadFileName = new String(filePath.getBytes("UTF-8"), "UTF-8");//设置编码
            headers.setContentDispositionFormData("attachment", downloadFileName);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            //MediaType:互联网媒介类型  contentType:具体请求中的媒体类型信息
            return new ResponseEntity(org.apache.commons.io.FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
        }

        
        public static boolean deleteFile(String filePath) throws IOException {
            File file = new File(filePath);
            if (!file.exists()) { //不存在返回false
                throw new IOException("不存在的文件");
            } else {
                file.delete();
                return true;
            }
        }
    }
}

文件上传fileController.java 文件 上传、下载、删除接口

package com.****.fileManage.controller;

import com.alibaba.fastjson.JSONObject;
import com.****.fileManage.annotation.ApiVersion;
import com.****.fileManage.common.model.ApibaseMessage;
import com.****.fileManage.common.model.FilePath;
import com.****.fileManage.common.model.JsonResult;
import com.****.fileManage.common.util.FileUtils;
import com.****.fileManage.config.ApiVersionConstant;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.linkedList;
import java.util.List;



@RestController
@RequestMapping("/file")
public class FileUploadController {
    private static final org.slf4j.Logger log=org.slf4j.LoggerFactory.getLogger(com.****.fileManage.controller.FileUploadController.class);

    @Value("${file.save.path}")
    private String defaultPath;

    @ApiOperation(value = "上传文件 - 单个")
    @ApiVersion({ApiVersionConstant.ONE_CRM_SPRINT_10})
    @RequestMapping(value = "upload", method = {RequestMethod.POST})
    @ResponseBody
    public ApibaseMessage fileUpload(@RequestParam("file") MultipartFile file, @RequestParam("type") String type, HttpServletRequest request){
        try {
            log.info("上传文件 - 单个开始");
            //这个别的微服务的接口,接收图片使用的参数名是headPortrait
            Collection parts = request.getParts();
            log.info(JSONObject.toJSonString(parts, true));
            List uploadFile=new linkedList();
            String path=defaultPath+File.separator+type.toUpperCase();
            FilePath fileResult = FileUtils.builder().setPathName(path).upload(file);
            uploadFile.add(fileResult);
            log.info("上传文件 - 单个完成");
            return ApibaseMessage.getSucceedInstance("30001", uploadFile);
        } catch (IOException e) {
            return ApibaseMessage.getSucceedInstance("30002", JsonResult.jsonErrorMsg(203,e.getMessage()));
        } catch (Exception e){
            return ApibaseMessage.getSucceedInstance("30002", JsonResult.jsonErrorMsg(500,e.getMessage()));
        }
    }


    @ApiOperation(value = "上传文件 - 多个")
    @ApiVersion({ApiVersionConstant.ONE_CRM_SPRINT_10})
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "type", value = "文件分类", dataType = "String")
    })
    @RequestMapping(value = "MultiUpload",method = {RequestMethod.POST})
    @ResponseBody
    public ApibaseMessage multiFileUpload(@RequestParam("files") MultipartFile[] files, @RequestParam("type") String type, HttpServletRequest request){
        try {
            log.info("上传文件 - 多个开始");
            //这个别的微服务的接口,接收图片使用的参数名是headPortrait
            Collection parts = request.getParts();
            log.info(JSONObject.toJSonString(parts, true));
            String path=defaultPath+File.separator+type.toUpperCase()+File.separator;
            List uploadFile=new linkedList();
            if(files!=null&&files.length>0){
                //循环获取file数组中得文件
                for(int i = 0;i download(@RequestParam String filePath) throws Exception {
        try {
            log.info("下载文件 - 开始");
            log.info("下载文件路径:" + filePath);
            ResponseEntity result = FileUtils.builder().download(filePath);
            log.info("下载文件 - 完成");
            return result;
        }catch (Exception e){
            throw e;
        }
    }

    @ApiOperation(value = "删除文件")
    @ApiVersion({ApiVersionConstant.ONE_CRM_SPRINT_10})
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "filePath", value = "文件路径", dataType = "String")
    })
    @RequestMapping(value = "delete",method = {RequestMethod.DELETE})
    @ResponseBody
    public ApibaseMessage deleteFile(@RequestParam String filePath) {
        try {
            log.info("删除文件 - 开始");
            log.info("删除文件-文件路径:"+filePath);
            boolean ifdelete = FileUtils.builder().deleteFile(filePath);
            log.info("删除文件 - 完成");
            return ApibaseMessage.getSucceedInstance("30001", ifdelete?"删除成功":"不存在的文件");
        }catch (IOException e) {
            return ApibaseMessage.getSucceedInstance("30002", JsonResult.jsonErrorMsg(204,e.getMessage()));
        } catch (Exception e){
            return ApibaseMessage.getSucceedInstance("30002", JsonResult.jsonErrorMsg(500,e.getMessage()));
        }
    }

}

7、综上完毕

文件服务器端代码,完成。将代码打包成jar,启动即可。启动脚本如下:

startup.sh 和 restart.sh

#!/bin/bash
java -jar ./filemanager-1.0.0.jar
ps -ef | grep filemanager-1.0.0.jar | grep -v grep | awk '{print $2}' | xargs kill -9
rm -rf nohup.out 
nohup ./startup.sh > nohup.out & 

至此文件服务器搭建完成,第二步骤就是应用端调用微服务接口了。参考下面文章!(7条消息) springboot文件服务器 二(IO流+微服务包含swagger、出入参统一格式、log4j2日志)_无敌小田田的博客-CSDN博客https://blog.csdn.net/qq_36602951/article/details/120772314

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/325568.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号