文件导入、导出、上传、下载

一、文件导入

1.单个sheet 表格数据导入

基于alibaba.easyexcel实现,这里直接上实现代码

          // conrtoller 层
    @PostMapping("/import")
    @ApiOperation(value = "批量导入区域信息")
    public ObjectRestResponse<ImportResultVo> importCreate(
            @RequestParam(value = "file") MultipartFile file) {
        ImportResultVo resultVo = areaService.importCreate(file);
        return new ObjectRestResponse<>().data(resultVo);
    }
/**  
     * service 层
     *  @author: xuyahui
     *  @Date: 2022/3/9 0:56
     *  @Description: 批量导入区域信息
     */
    public ImportResultVo importCreate(MultipartFile file) {
        try {
            ModelExcelListener<AreaExcelVo> listener = new ModelExcelListener<>();
            EasyExcel.read(file.getInputStream(), AreaExcelVo.class,listener).sheet(0).doRead();
            List<AreaExcelVo> importList = listener.getList();

            if (CollectionUtils.isEmpty(importList)){
                return ImportResultVo.buildFail("导入失败,文件没有数据");
            }

            AreaExcelVo firstVo = importList.get(0);
            List<String> desc = EasyExcelUtil.getDesc(AreaExcelVo.class);
            if (!CollectionUtils.isEmpty(desc) && desc.get(0).equals(firstVo.getCode())){
                //如果是描述,则移除
                importList.remove(0);
            }

            List<AreaExcelVo> checkedList = new ArrayList<>();// 验证通过的数据
            List<ImportErrorVo> errorList = new ArrayList<>();// 验证失败的错误信息集合
            for (AreaExcelVo importVo : importList) {
                String errorInfo = ValidatorUtil.validateReturnFirstError(importVo);
                if (StringUtils.hasText(errorInfo)){
                    errorList.add(ImportErrorVo.build(importVo.getRowIndex(),errorInfo));
                    continue;
                }
                checkedList.add(importVo);
            }
            if (CollectionUtils.isEmpty(checkedList)){
                return ImportResultVo.buildFail(errorList);
            }

            //业务校验 区域编码是否存在
            Map<String, AreaExcelVo> importAreaMap = checkedList.stream().collect(Collectors.toMap(AreaExcelVo::getCode,
                    Function.identity(),(k1, k2) -> k1));
            List<Area> areaList = areaMapper.listAll();
            Map<String, Area> areaMap = areaList.stream().collect(Collectors.toMap(Area::getCode, Function.identity(), (k1, k2) -> k2));

            Iterator<String> iterator = importAreaMap.keySet().iterator();
            while (iterator.hasNext()) {
                String importKey =  iterator.next();
                if (areaMap.containsKey(importKey)){
                    //数据库已存在
                    AreaExcelVo importVo = importAreaMap.get(importKey);
                    errorList.add(ImportErrorVo.build(importVo.getRowIndex(),"区域编码重复"));
                    iterator.remove();
                    importAreaMap.remove(importKey);
                }
            }

            if (!CollectionUtils.isEmpty(errorList)){
                List<ImportErrorVo> sortedErrorList = errorList.stream().sorted(Comparator.comparing(ImportErrorVo::getRowIndex)).collect(Collectors.toList());
                return ImportResultVo.buildFail(sortedErrorList);
            }

            List<Area> saveAreaList = new ArrayList<>();
            for (Map.Entry<String, AreaExcelVo> entry : importAreaMap.entrySet()) {
                AreaExcelVo excelVo = entry.getValue();
                Area area = Area.buildImportEntity(excelVo);
                area.setId(SnowflakeIdUtil.nextId());
                saveAreaList.add(area);
            }
            areaMapper.batchInsert(saveAreaList);
            return ImportResultVo.buildSuccess(importAreaMap.size());
        }catch (Exception e){
            log.error("区域导入异常 ==>{}",e.getMessage(),e);
            return ImportResultVo.buildFail(e.getMessage());
        }

    }

下面是相关的验证和处理类

package com.spring.mes.common.util.easyexcel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.spring.mes.common.util.easyexcel.EasyExcelUtil;
import com.spring.mes.pojo.msg.exception.BaseException;
import com.spring.mes.pojo.vo.basic.excel.ExcelModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 实体类模板的导入
 *
 * @author maji
 */
@Slf4j
@Data
@EqualsAndHashCode(callSuper=false)
public class ModelExcelListener<T extends ExcelModel> extends AnalysisEventListener<T> {

    //一次允许多少条数据导入
    private int batchCount = 10000;

    //用list集合保存解析到的结果
    private List<T> list = new ArrayList<>();

    //表头
    private Map<Integer,Map<Integer,String>> headMap = new HashMap<>();



    /**
     * 取时,使用实体类读取表头,否则只会默认读第一行为表头
     * EasyExcel.read(file.getInputStream(), 实体类.class,listener).sheet(0).doRead();
     * @param excelHead
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> excelHead, AnalysisContext context) {
        // 读取时,使用实体类读取表头,否则只会默认读第一行为表头
        //EasyExcel.read(file.getInputStream(), 实体类.class,listener).sheet(0).doRead();
        Integer rowIndex = context.readRowHolder().getRowIndex();
        //生成表头并校验
        Class tClass = context.currentReadHolder().excelReadHeadProperty().getHeadClazz();
        if (CollectionUtils.isEmpty(headMap)){
            headMap = EasyExcelUtil.getHeadMap(tClass);
        }
        //校验表头
        Map<Integer, String> classHead = headMap.get(rowIndex);
        if (!excelHead.equals(classHead)){
            //此处异常会走到 onException方法,不管什么异常都会被转成 ExcelAnalysisException
            throw new ExcelAnalysisException("表头校验异常,请使用正确的模板进行导入");
        }
    }


    @Override
    public void invoke(T data, AnalysisContext context) {
        Integer rowIndex = context.readRowHolder().getRowIndex();
        data.setRowIndex(rowIndex + 1);

        list.add(data);
        if (list.size() > batchCount) {
            //此处异常会走到 onException方法,不管什么异常都会被转成 ExcelAnalysisException
            throw new ExcelAnalysisException("导入条数超过限制,最多导入"+batchCount+"条");
        }
    }

    /**
     * 解析到最后会进入这个方法,需要则重写这个doAfterAllAnalysed方法
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (CollectionUtils.isEmpty(list)){
            //此处异常不会走到 onException 方法
            throw new ExcelAnalysisException("导入失败,文件没有数据");
        }
    }


    /**
     * 在有异常时,抛出异常则停止读取。如果这里不抛出异常则 会继续读取下一行。
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        // 此处抛的异常都会在 AbstractReadHolder类中 转成 ExcelAnalysisException 异常
        Integer rowIndex = context.readRowHolder().getRowIndex();
        if (rowIndex == headMap.size()){
            //如果是表头下一行的数据异常,放行,防止是因为 字段描述 造成的异常
            return;
        }
        ExcelDataConvertException excelDataConvertException = null;
        if (exception instanceof ExcelDataConvertException) {
            excelDataConvertException = (ExcelDataConvertException) exception;
            String errorConvert = String.format("第%s行第%s列,解析异常",excelDataConvertException.getRowIndex()+1,
                    excelDataConvertException.getColumnIndex()+1);
            throw new ExcelAnalysisException(errorConvert);
        } else{
            throw exception;
        }
    }

}
package com.spring.mes.common.util.easyexcel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.spring.mes.common.util.FieldTool;
import com.spring.mes.common.util.easyexcel.handler.ColumnAutoWidthHandler;
import com.spring.mes.common.util.easyexcel.handler.HiddenSheetSpinnerWriteHandler;
import com.spring.mes.pojo.ExcelFieldDesc;
import com.spring.mes.pojo.msg.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.IndexedColors;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * easyExcel 简单工具类
 *
 * @author maji
 */
@Slf4j
public class EasyExcelUtil {

    public static String[] specialCharArr = {"[", "]", "?", "*", "/", "\\"};


    /**
     * 获取最基础的ExcelWriter
     *
     * @param response
     * @param fileName 导出文件名
     */
    public static ExcelWriter getExcelWriter(HttpServletResponse response, String fileName) {
        try {
            return getExcelWriterBuilder(response, fileName)
                    .registerWriteHandler(new ColumnAutoWidthHandler())
                    .registerWriteHandler(new HorizontalCellStyleStrategy(styleHead(), styleCells()))
                    .build();
        } catch (Exception e) {
            log.error("getExcelWriter fail ==>{}", e);
        }
        return null;

    }

    /**
     * 获取ExcelWriterBuilder
     *
     * @param response
     * @param fileName 导出文件名
     */
    public static ExcelWriterBuilder getExcelWriterBuilder(HttpServletResponse response, String fileName) {
        try {
            return EasyExcel.write(getServletOutputStream(response, fileName));
        } catch (Exception e) {
            log.error("getExcelWriterBuilder fail ==>{}", e);
        }
        return null;

    }

    /**
     * 获取输出流
     *
     * @param response
     * @param fileName
     * @return
     * @throws IOException
     */
    public static ServletOutputStream getServletOutputStream(HttpServletResponse response, String fileName) throws IOException {
        fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "no-store");
        response.addHeader("Cache-Control", "max-age=0");
        return response.getOutputStream();
    }


    /**
     * 导出模板
     * @param response
     * @param headClass
     * @param fileSheetName
     */
    public static void downloadTemplate(HttpServletResponse response,Class headClass,String fileSheetName) {
        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcelUtil.getExcelWriter(response, fileSheetName);

            WriteSheet writeSheet = EasyExcel.writerSheet()
                    .head(headClass)
                    .sheetName(fileSheetName)
                    .build();
            //设置第二行为字段说明
            excelWriter.write(Collections.singletonList(EasyExcelUtil.getDesc(headClass)), writeSheet);

            excelWriter.finish();
        }catch (Exception e) {
            log.error("导出模板失败!", e);
            throw new BaseException("导出模板失败");
        }finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    /**
     * 导出模板,单元格中设置下拉框选项
     */
    public static void downloadTemplate(HttpServletResponse response,Class headClass,String fileSheetName,Map<Integer, List<String>> dropDownMap) {
        ExcelWriter excelWriter = null;
        try {
            //选项放下拉框,第一行表头,第2行字段说明,第三行开始放下拉框
            HiddenSheetSpinnerWriteHandler spinnerWriteHandler = HiddenSheetSpinnerWriteHandler.builder().dropDownMap(dropDownMap).firstRow(2).build();
            excelWriter = EasyExcelUtil.getExcelWriterBuilder(response, fileSheetName)
                    .registerWriteHandler(new ColumnAutoWidthHandler())
                    .registerWriteHandler(new HorizontalCellStyleStrategy(EasyExcelUtil.styleHead(), EasyExcelUtil.styleCells()))
                    .registerWriteHandler(spinnerWriteHandler)
                    .build();

            WriteSheet writeSheet = EasyExcel.writerSheet()
                    .head(headClass)
                    .sheetName(fileSheetName)
                    .build();
            //设置第二行为字段说明
            excelWriter.write(Collections.singletonList(EasyExcelUtil.getDesc(headClass)), writeSheet);

            excelWriter.finish();
        }catch (Exception e) {
            log.error("导出模板失败!", e);
            throw new BaseException("导出模板失败");
        }finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    /**
     * 导出固定表头的数据
     */
    public static void exportData(HttpServletResponse response, String fileSheetName, Class headClass, List<? extends Object> dataList) {

        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcelUtil.getExcelWriter(response, fileSheetName);

            WriteSheet writeSheet = EasyExcel.writerSheet()
                    .head(headClass)
                    .sheetName(fileSheetName)
                    .build();
            excelWriter.write(dataList, writeSheet);

            excelWriter.finish();
        }catch (Exception e) {
            log.error("导出"+fileSheetName+"失败!", e);
            throw new BaseException("导出数据失败");
        }finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }

    }

    /**
     * 表头样式
     * */
    public static WriteCellStyle styleHead() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 设置背景色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());

        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setBold(true);
        headWriteFont.setFontHeightInPoints((short)14);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 设置边框
        setBorder(headWriteCellStyle);
        return headWriteCellStyle;
    }

    /**
     * 内容样式
     * */
    public static WriteCellStyle styleCells() {
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        return setBorder(contentWriteCellStyle);
    }

    /**
     * 设置边框
     * */
    private static WriteCellStyle setBorder(WriteCellStyle style) {
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }


    /**
     * 获取模板实体类中的说明
     * @param clazz
     * @return
     */
    public static List<String> getDesc(Class clazz) {
        List<Field> fields = FieldTool.getDeclaredFields(clazz);
        List<String> descList = new ArrayList<>();
        for (Field field : fields) {
            ExcelProperty property = field.getAnnotation(ExcelProperty.class);
            if (property != null) {
                ExcelFieldDesc desc = field.getAnnotation(ExcelFieldDesc.class);
                if (desc != null) {
                    descList.add(desc.value());
                }else {
                    descList.add("");
                }
            }
        }
        return descList;
    }


    /**
     * 从模板实体类中转换表头
     * @param clazz
     * @return
     */
    public static Map<Integer,Map<Integer,String>> getHeadMap(Class clazz) {
        List<Field> fields = FieldTool.getDeclaredFields(clazz);
        Integer index = 0;
        //正常只有一行表头,但可能也有多行,key 从0 开始
        Map<Integer,Map<Integer,String>> headMap = new HashMap<>();
        for (Field field : fields) {
            ExcelIgnore ignore = field.getAnnotation(ExcelIgnore.class);
            if (ignore != null){
                continue;
            }
            ExcelProperty property = field.getAnnotation(ExcelProperty.class);
            if (property != null) {
                String[] values = property.value();
                for (int i = 0; i < values.length; i++) {
                    Map<Integer, String> headRow = headMap.get(i);
                    if (headRow == null){
                        headRow = new HashMap<>();
                        headMap.put(i,headRow);
                    }
                    headRow.put(index,values[i]);
                }
                index ++ ;
            }
        }
        return headMap;
    }


    /**
     * sheetName 去除特殊字符
     *
     * @param sheetName
     * @return
     */
    public static String checkSheetName(String sheetName) {
        for (String s : specialCharArr) {
            sheetName = StringUtils.replace(sheetName, s, "");
        }
        return sheetName;
    }


    /**
     * 自定义表头
     *
     * @param headList sheet表头
     */
    public static List<List<String>> getHead(Collection<String> headList) {
        List<List<String>> list = new ArrayList<>();
        if (headList != null) {
            headList.forEach(h -> list.add(Collections.singletonList(h)));
        }
        return list;
    }

}
package com.spring.mes.common.util;

import lombok.experimental.UtilityClass;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.List;
import java.util.stream.Collectors;

@UtilityClass
public class ValidatorUtil {

    private final Validator validator;

    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    public List<String> validate(Object object, Class<?>... groups) {

        return validator.validate(object, groups)
                .stream().map(ConstraintViolation::getMessage)
                .collect(Collectors.toList());

    }

    public static String validateReturnFirstError(Object object){
        return validator.validate(object)
                .stream().findFirst().map(ConstraintViolation::getMessage)
                .orElse(null);
    }
}
package com.spring.mes.pojo.vo.basic.excel;

import com.alibaba.excel.annotation.ExcelIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

@Data
@NoArgsConstructor
public class ImportResultVo implements Serializable {

    @ApiModelProperty(value = "是否导入成功")
    private Boolean success;

    @ApiModelProperty(value = "成功数量")
    private Integer successNum;

    @ApiModelProperty(value = "单独的异常信息")
    private String errorMsg;

    @ApiModelProperty(value = "异常行信息集合")
    private List<ImportErrorVo> errorList;

    @ApiModelProperty(value = "导入成功的对象集合")
    private List<Object> list;

    public static ImportResultVo buildFail(String errorMsg) {
        ImportResultVo vo = new ImportResultVo();
        vo.setSuccess(false);
        vo.setErrorMsg(errorMsg);
        return vo;
    }

    public static ImportResultVo buildFail(List<ImportErrorVo> errorList) {
        ImportResultVo vo = new ImportResultVo();
        vo.setSuccess(false);
        vo.setErrorMsg("部分数据导入失败,请重新导入!");
        vo.setErrorList(errorList);
        return vo;
    }

    public static ImportResultVo buildSuccess(Integer successNum) {
        ImportResultVo vo = new ImportResultVo();
        vo.setSuccess(true);
        vo.setSuccessNum(successNum);
        return vo;
    }
    public static ImportResultVo buildItemList(List<Object> list) {
        ImportResultVo vo = new ImportResultVo();
        vo.setSuccess(true);
        vo.setList(list);
        vo.setSuccessNum(list.size());
        return vo;
    }

    public static ImportResultVo buildErrAndOkItemList(List<ImportErrorVo> errorList,List<Object> list) {
        ImportResultVo vo = new ImportResultVo();
        vo.setSuccess(false);
        vo.setErrorMsg("部分数据导入失败,请重新导入!");
        vo.setErrorList(errorList);
        vo.setSuccess(true);
        vo.setList(list);
        return vo;
    }


}

2.多个sheet表格数据导入

@ApiOperation(value = "批量导入用户")
    @PostMapping("/import")
    @SysLog(value = "导入用户",module = LogModuleConstants.USER_CENTER,menu = LogMenuConstants.USER)
    public ResponseBody importCreate(@RequestParam(value = "file",required = false) MultipartFile file) {
        UserImportResultVo  resultVo = userService.importCreate(file);
        return ResponseBody.success(resultVo);
    }


/**
     * @author: xuyahui
     * @Date: 2021/4/7 14:11
     * @Description: 批量导入用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserImportResultVo importCreate(MultipartFile file) {
        try {
            InputStream in = file.getInputStream();
            ExcelReader excelReader = EasyExcel.read(in).build();
            PhoneListener phoneListener = new PhoneListener(this);
            EmailListener emailListener = new EmailListener(this);
            UsernameListener usernameListener = new UsernameListener(this);

            //获取sheet对象
            ReadSheet phoneSheet =
                    EasyExcel.readSheet(0).head(PhoneImportTemplate.class).registerReadListener(phoneListener).build();
            ReadSheet emailSheet =
                    EasyExcel.readSheet(1).head(EmailImportTemplate.class).registerReadListener(emailListener).build();
            ReadSheet usernameSheet =
                    EasyExcel.readSheet(2).head(UsernameImportTemplate.class).registerReadListener(usernameListener).build();

            // 业务处理
            excelReader.read(phoneSheet, emailSheet, usernameSheet);

            return convertAndSave(phoneListener, emailListener, usernameListener);
        } catch (IOException e) {
            log.error("批量导入用户失败!");
        }
        return null;
    }


/**
     * @author: xuyahui
     * @Date: 2021/5/8 15:49
     * @Description: 转换并保存数据
     */
    private UserImportResultVo convertAndSave(PhoneListener phoneListener,
                                              EmailListener emailListener,
                                              UsernameListener usernameListener) {

        List<PhoneImportTemplate> phoneUserList = phoneListener.getData();
        List<EmailImportTemplate> emailUserList = emailListener.getData();
        List<UsernameImportTemplate> usernameUserList = usernameListener.getData();

        // 验证表头
        checkTableHead(phoneListener.getHeadMap(),emailListener.getHeadMap(),usernameListener.getHeadMap());

        // 验证数据
        checkImportUserInfo(phoneUserList, emailUserList, usernameUserList);

        List<UserImportVo> userImportVoList = buildImportUserVoList(phoneUserList, emailUserList, usernameUserList);
        SysOrganizationEntity company = organizationBiz.selectById(SessionBean.getTenantId());

        // 处理数据
        int successNum = 0;
        List<SysOrganizationUserRel> organizationUserRels = null;
        List<SysRoleUserRel> sysRoleUserRelList = null;
        for (UserImportVo importUser : userImportVoList) {
            // 查询组织机构和角色
            organizationUserRels = new ArrayList<>();
            sysRoleUserRelList = new ArrayList<>();
            SysOrganizationEntity organization = organizationBiz.selectByOrgName(importUser.getOrganization());
            SysRoleEntity roleEntity = sysRoleBiz.selectByNameAndTenantId(importUser.getRole(), SessionBean.getTenantId());

            SysUserEntity user = ObjectCopyUtil.objectCopy(importUser, SysUserEntity.class);
            initUser(user);
            SysOrganizationUserRel companyUserRel = buildUserOrganizationRel(user.getId(), SessionBean.getTenantId(), null, SessionBean.getTenantId(), true);
            organizationUserRels.add(companyUserRel);

            if (!Objects.isNull(organization)) {
                SysOrganizationUserRel orgRel = buildUserOrganizationRel(user.getId(), null, organization.getId(), SessionBean.getTenantId(), true);
                organizationUserRels.add(orgRel);
            }
            if (!Objects.isNull(roleEntity)) {
                SysRoleUserRel roleUserRel = SysRoleUserRel.create(user, roleEntity);
                sysRoleUserRelList.add(roleUserRel);
            }

            // 查询验证角色是否有管理员
            SysRoleEntity addAdminRole = getAdminRole(sysRoleUserRelList);
            sysUserBiz.insertUser(user, organizationUserRels, sysRoleUserRelList, companyUserRel);
            // 平台创建
            try {
                createPlatUser(user, company, organizationUserRels);
                if (Objects.nonNull(addAdminRole)) {// 新增组织管理员
                    aclServiceFeign.addUserToOrganizationAdmin(SessionBean.getTenantId(), user.getId());
                }
                successNum++;
            } catch (Exception e) {
                sysUserBiz.deleteMetaUserById(user.getId());
                sysUserBiz.deleteUserById(user.getId());
            }
        }
        return UserImportResultVo.build(userImportVoList.size(), successNum);
    }

3.带参数的文件导入

除了文件,还有对象信息的参数,请求参数可以放在form-data里面,具体示例如下:

(1)controller 类中代码写法

/**
     * 上传模型
     * @param abFile
     * @param jpgFile
     * @param sxEquipment
     * @return
     * @throws IOException
     */
    @PreAuthorize("@ss.hasAnyPermi('asset:workshop:add,asset:device:add,asset:facilities:add')")
    @PostMapping("/addEquipment")
    public AjaxResult addEquipment(MultipartFile abFile, MultipartFile jpgFile,SxEquipment sxEquipment) throws IOException {
        try {
            List<SxEquipment> sxEquipmentlist = sxEquipmentService.selectListEq(sxEquipment);
            if (sxEquipmentlist.size() > 0) return AjaxResult.error("设备已存在");
            sxEquipment.setModelTime(DateUtils.getNowDate());
//            sxEquipment.setCreateBy(SecurityUtils.getLoginUser().getUser().getUserName());
            sxEquipment.setThumbTime(DateUtils.getNowDate());
            sxEquipment.setCreateFlag("0");
            sxEquipment.setBrowseNum(0);
            sxEquipment.setDownloadNum(0);
//            sxEquipment.setCompanyName("火星视觉数字科技有限公司");
            sxEquipment.setCreateTime(DateUtils.getNowDate());
            sxEquipmentService.save(sxEquipment);
            if (Objects.nonNull(abFile)) {
//                String abUrl = FileUploadUtils.mixstationA(abFile, 1, sxEquipment.getEquipmentId());
                String abUrl = ossService.mixstation1(abFile, 1, sxEquipment.getEquipmentId());
                sxEquipment.setModel(abUrl);
            }
            String jpgUrl = ossService.mixstation1(jpgFile, 0, sxEquipment.getEquipmentId());
            sxEquipment.setPic(jpgUrl);

            sxEquipmentService.updateEquipmentById(sxEquipment);
            if (Objects.nonNull(sxEquipment.getPic())) sxEquipment.setThumbTime(DateUtils.getNowDate());
            return AjaxResult.success();
        } catch (Exception e) {
            throw new IOException(e.getMessage(), e);
        }

    }

(2)apifox请求示例:

二、文件导出


    // controller 层
    @PostMapping(value = "/export")
    @ApiOperation(value = "区域信息导出")
    public void export(HttpServletResponse response, @RequestBody AreaQueryDto dto){
        log.info("区域信息导出==>{}", JSON.toJSONString(dto));
        areaService.export(response,dto);
    }
/**
     *  @author: xuyahui
     *  @Date: 2022/3/4 11:16
     *  @Description: 区域信息导出
     */
    public void export(HttpServletResponse response, AreaQueryDto dto) {
            List<AreaExcelVo> resultList = getExportResultList(dto);

            String fileSheetName = "区域";
            ExcelWriter excelWriter = null;
            try {
                excelWriter = EasyExcelUtil.getExcelWriter(response, fileSheetName+"_"+ DateUtils.format(new Date()));

                WriteSheet writeSheet = EasyExcel.writerSheet()
                        .head(AreaExcelVo.class)
                        .sheetName(fileSheetName)
                        .build();
                excelWriter.write(resultList, writeSheet);

                excelWriter.finish();
            }catch (Exception e) {
                log.error("导出区域信息失败!", e);
                throw new BaseException("导出区域信息失败");
            }finally {
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }

    }

        /**
     *  @author: xuyahui
     *  @Date: 2022/3/4 11:25
     *  @Description: 获取区域导出信息
     */
    private List<AreaExcelVo> getExportResultList(AreaQueryDto dto) {
        List<Area> areaList = areaMapper.filterArea(dto);
        if(CollectionUtils.isEmpty(areaList)){
            return Lists.newArrayList();
        }
        List<AreaExcelVo> areaExcelVoList = areaList.stream().map(v->v.buildExportVo()).collect(Collectors.toList());
        return areaExcelVoList;
    }

三、下载导入模板

1.多个sheet实现

 @ApiOperation(value = "下载用户导入模板")
    @GetMapping("/template")
    public void downloadTemplate(HttpServletResponse response) {
        log.info("下载用户导入模板");
        userService.downloadTemplate(response);
    }

@Override
    public void downloadTemplate(HttpServletResponse response) {
        try {
            ResourceBundle resourceBundle = i18nSet();
            String fileName = URLEncoder.encode(resourceBundle.getString("EXCEL_USER_TEMPLATE"), "UTF-8");
//            String fileName = URLEncoder.encode("用户导入模板", "UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

            List<SysRoleEntity> sysRoleEntityList = sysRoleBiz.listAll(SessionBean.getTenantId());
            List<String> roleNameList = sysRoleEntityList.stream()
                    .filter(role -> (0 != role.getRoleType() && 1 != role.getRoleType()))
                    .map(SysRoleEntity::getRoleName).collect(Collectors.toList());

            Set<String> authorizedOrgIdSet = userService.getUserAuthorizedOrgIdList(SessionBean.getUserId());
            List<SysOrganizationEntity> organizationList = organizationBiz.listByIds(authorizedOrgIdSet);
            List<String> organizationNameList = organizationList.stream().map(SysOrganizationEntity::getOrganizationName).collect(Collectors.toList());

            WriteSheet phoneSheet = buildPhoneSheet(roleNameList, organizationNameList,resourceBundle);
            WriteSheet emailSheet = buildEmailSheet(roleNameList, organizationNameList,resourceBundle);
            WriteSheet usernameSheet = buildUserNameSheet(roleNameList, organizationNameList,resourceBundle);

            String displayNameDesc = resourceBundle.getString("EXCEL_DISPLAYNAME_DESC");
            String phoneDesc = resourceBundle.getString("EXCEL_HPONE_DESC");
            String emailDesc = resourceBundle.getString("EXCEL_EMAIL_DESC");
            String userNameDesc = resourceBundle.getString("EXCEL_USERNAME_DESC");
            String pwdDesc = resourceBundle.getString("EXCEL_PASSWORD_DESC");

            List<String> phoneDescs = Arrays.asList(displayNameDesc, phoneDesc, "", "");
            List<String> emailDescs = Arrays.asList(displayNameDesc, emailDesc, "", "");
            List<String> usernameDescs = Arrays.asList(displayNameDesc, userNameDesc, pwdDesc, "", "");

            // 写入数据
            excelWriter.write(Collections.singletonList(phoneDescs), phoneSheet)
                    .write(Collections.singletonList(emailDescs), emailSheet)
                    .write(Collections.singletonList(usernameDescs), usernameSheet);
            excelWriter.finish();
        } catch (Exception e) {
            log.error("[excelExport] error:", e);
        }

    }

四、文件上传

1.文件上传实现方法一(基于Minio实现)

@PostMapping(value = "/upload")
    @ApiOperation(value = "上传文件返回文件存储名称", httpMethod = "POST", notes = "上传文件返回文件存储名称")
    public String upload(@RequestParam("file") MultipartFile file,
                         @RequestParam("bucketName") String bucketName,
                         @RequestParam("childBucketName") String childBucketName,
                         @RequestParam(required = false) Boolean previewFlag) throws Exception {
        log.info("上传文件返回可下载地址,fileName{},businessName{}",childBucketName);
        return minioYunService.uploadFile(file,bucketName,childBucketName,previewFlag);
    }


public String uploadFile(MultipartFile file,
                             String bucketName,
                             String childBucketName,
                             Boolean previewFlag) throws Exception {
        String fileName = file.getOriginalFilename();
        fileName = fileName.substring(Constants.ZERO,fileName.lastIndexOf(Constants.POINT)) + Constants.UNDERLINE
                    + System.currentTimeMillis() + Constants.POINT
                    + fileName.substring(fileName.lastIndexOf(Constants.POINT) + Constants.ONE);
        return upload(file, fileName, Constants.CONTENT_TYPE_STREAM,bucketName,childBucketName, previewFlag);
    }


private String upload(MultipartFile file, String fileName, String contentType, String bucketName,String childBucketName, Boolean previewFlag) throws Exception {
        previewFlag = null == previewFlag ? true : previewFlag;
        log.info("上传文件参数:fileName:{},bucketName:{},childBucketName:{}",fileName,bucketName,childBucketName);
        client = new MinioClient(constants.getEndpoint(), constants.getAccessKey(), constants.getSecretKey());

        String objectName = Objects.isNull(childBucketName) ? fileName : childBucketName + "/" + fileName;
        //创建文件流
        InputStream inputStream = file.getInputStream();
        log.info("参数 文件夹名称+文件名称"+objectName);
        try {
            boolean isExist = client.bucketExists(bucketName);
            if (isExist) {
                log.debug("桶[{}]已经存在", bucketName);
            } else {
                //新建桶
                client.makeBucket(bucketName);
            }
            if (!previewFlag) {
                client.putObject(bucketName, objectName, inputStream, contentType);
            } else {
                client.putObject(bucketName, objectName, inputStream, FileContentTypeUtil.getContentType(fileName));
            }
            inputStream.close();
        } catch (Exception e) {
            log.error("file update error" + e);
        }
        return objectName;
    }


public class FileContentTypeUtil {

    public static String getContentType(String fileName) {
        String type = fileName.substring(fileName.lastIndexOf(".")+1);
        String contentType = Constants.CONTENT_TYPE_STREAM;
        if (StringUtils.isNotBlank(type)) {
            if (type.equals("jpg") || type.equals("jpeg")) {
                contentType = "image/jpeg";
            }
            if (type.equals("png")) {
                contentType = "image/png";
            }
            if (type.equals("gif")) {
                contentType = "image/gif";
            }
            if (type.equals("mp4")) {
                contentType = "video/mp4";
            }
            if (type.equals("wmv")) {
                contentType = "video/x-ms-wmv";
            }
            if (type.equals("ogg")) {
                contentType = "video/x-theora+ogg";
            }
        }
        return contentType;
    }
    
}

2.文件上传实现方法二(基于Minio实现)

controller 层代码

@RequestMapping(value = "/publicUpload", method = RequestMethod.POST)
    @ApiOperation(value = "上传文件接口", notes = "")
    @ApiImplicitParam(paramType = "header", dataType = "String", name = "workspaceId", value = "工作空间id", required = true)
    @ResponseBody
    public ObjectRestResponse<DsFileVo> publicUploadFile(@ApiParam("上传文件") @RequestParam("file") MultipartFile multipartFile,
                                                         @ApiParam("文件名称") @RequestParam(value = "fileName", required = false)
                                                         @Length(max = ValidatorConstant.COMMON_LENGTH_64, message = "文件名称" + ValidatorConstant.COMMON_LENGTH_64_MSG)
                                                         @Pattern(regexp = ValidatorConstant.CONVENTIONAL_TEXT_REG, message = "文件名称只能包含" + ValidatorConstant.CONVENTIONAL_TEXT_REG_MSG)
                                                                     String fileName,
                                                         @ApiParam("存储文件加夹名字") @RequestParam(value = "folderName", required = false) String folderName
                                            ) throws IOException, XmlPullParserException, NoSuchAlgorithmException, RegionConflictException, InvalidKeyException, InvalidPortException, InvalidArgumentException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InvalidEndpointException, InternalException, InvalidObjectPrefixException {
        if (null == multipartFile) {
            throw new BaseException("上传文件不能为空", ErrorType.ERROR_REQUEST_FAILD.getIndex());
        }
        DsFileVo fileVo = fileService.publicUploadFile(multipartFile, fileName,folderName);
        return new ObjectRestResponse().data(fileVo);
    }

service 层代码

/**
     *
     * @param multipartFile
     * @param fileName  文件名
     * @param folderName Minio服务存储文件夹的文件夹名
     * @return
     */
    public DsFileVo publicUploadFile(MultipartFile multipartFile, String fileName,String folderName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, XmlPullParserException, InvalidPortException, InvalidArgumentException, InternalException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InvalidEndpointException, RegionConflictException, InvalidObjectPrefixException{
        String fileOriginalName = multipartFile.getOriginalFilename();
        if (StringUtils.isEmpty(fileOriginalName)) {
            throw new BaseException("文件原始名称缺失");
        }
        String extension = fileUtil.checkFileExtension(fileOriginalName);
        DsFileVo dsFileVo = new DsFileVo();
        String fileAbsolutePath = getFileAbsolutePath(folderName, fileOriginalName);
        String fileRelativePath = getFileRelativePath(fileAbsolutePath);
        InputStream ins = multipartFile.getInputStream();
        File targetFile = null;
        try {
            targetFile = new File(fileRelativePath.substring(fileRelativePath.lastIndexOf("/") + 1));
            FileUtils.copyInputStreamToFile(ins, targetFile);
            String fileSize = fileUtil.getFileSize(targetFile);
            fileUtil.saveMultiFile(targetFile.getName(), server, multipartFile, folderName+ "/" + LocalDate.now().toString());
            DsFile dsFile = initLocalDsFile1(fileOriginalName, fileName,  fileSize, fileRelativePath, extension);
            ObjectCopyUtil.objectPropertiesCopy(dsFile, dsFileVo);
        } catch (Exception ex) {
            fileUtil.deleteFile(folderName,fileRelativePath);
            throw ex;
        } finally {
            ins.close();
            if (targetFile != null && targetFile.exists()) {
                targetFile.delete();
            }
        }
        return dsFileVo;
    }


/**
     * 获取文件存放绝对路径
     *
     * @param workspaceId
     * @param fileOriginalName
     * @return
     */
    public String getFileAbsolutePath(String workspaceId, String fileOriginalName) {
        String filePath = getFileParentPath(workspaceId) + "/" + fileUtil.getFileRandomName(fileOriginalName);
        return filePath;
    }

  /**
     * 获取空间文档默认存放路径
     *
     * @param workspaceId
     * @return
     */
    public String getFileParentPath(String workspaceId) {
        String path = fileUtil.getDefaultRootPath() + "/" + server + "/" + workspaceId + "/" + LocalDate.now().toString();
        File temp = new File(path);
        if (!temp.exists()) {
            if (!temp.mkdirs()) {
                throw new BaseException("创建文件存储路径失败");
            }
        }
        return temp.getAbsolutePath();
    }

/**
     * 根据文件原始名称,获取一个随机名称:xxx-xx...x-xxxx.txt
     *
     * @param fileOriginalName
     * @return
     */
    public String getFileRandomName(String fileOriginalName) {
        String extension = StringUtils.getFilenameExtension(fileOriginalName);
        String resourceId = UUID.randomUUID().toString();
        if (StringUtils.isEmpty(extension)) {
            return resourceId;
        } else {
            return resourceId + "." + extension;
        }
    }

/**
     * 从空间开始的相对路径
     *
     * @param fileAbsolutePath
     * @return
     */
    public String getFileRelativePath(String fileAbsolutePath) {
        String defaultRootPath = fileUtil.getDefaultRootPath();
        if (fileAbsolutePath.contains(defaultRootPath)) {
            return fileAbsolutePath.replace(defaultRootPath, "").replaceAll("\\\\", "/");
        } else {
            throw new BaseException("获取文件相对路径失败");
        }
    }

    /**
     * 获取默认路径
     *
     * @return
     */
    public String getDefaultRootPath() {
        String rootJarPath = getBaseJarPath().getAbsolutePath();
        File defaultFile = new File(rootJarPath + "/" + DEFAULT_PATH);
        if (!defaultFile.exists()) {
            if (!defaultFile.mkdirs()) {
                throw new BaseException("创建默认存放路径失败", ErrorType.ERROR.getIndex());
            }
        }
        return defaultFile.getAbsolutePath();
    }

minio文件存储实现

 public void saveMultiFile(String fileName, String space, MultipartFile file, String filePath) throws IOException, XmlPullParserException, NoSuchAlgorithmException, RegionConflictException, InvalidKeyException, InvalidPortException, InvalidArgumentException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InvalidEndpointException, InternalException, InvalidObjectPrefixException {
        minioUtil.saveFile(fileName, space, file, filePath);
    }

    public void saveFile(String fileName, String space, MultipartFile file, String filePath) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException, RegionConflictException, InvalidArgumentException, InvalidObjectPrefixException {
        boolean isExist = template.getMinioClient().bucketExists(space);
        if (!isExist) {
            template.createBucket(space);
        }
        template.getMinioClient().setBucketPolicy(space,filePath,PolicyType.NONE);
        template.saveObject(space , filePath + "/" + fileName ,file.getInputStream(),file.getSize(),file.getContentType());
    }
package com.spring.doc.minio.service;

import com.spring.doc.minio.vo.MinioItem;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.xmlpull.v1.XmlPullParserException;

import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


public class MinioTemplate {

    private String endpoint, accessKey, secretKey;

    public MinioTemplate() {
    }

    /**
     * Create new instance of the {@link MinioTemplate} with the access key and secret key.
     *
     * @param endpoint  minio URL, it should be a  URL, domain name, IPv4 address or IPv6 address
     * @param accessKey uniquely identifies a minio account.
     * @param secretKey the password to a minio account.
     */
    public MinioTemplate(String endpoint, String accessKey, String secretKey) {
        this.endpoint = endpoint;
        this.accessKey = accessKey;
        this.secretKey = secretKey;
    }

    /**
     * Bucket Operations
     */

    public void createBucket(String bucketName) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidPortException, InvalidEndpointException, RegionConflictException, NoResponseException, InternalException, ErrorResponseException, InsufficientDataException, InvalidBucketNameException {
        MinioClient client = getMinioClient();
        if (!client.bucketExists(bucketName)) {
            client.makeBucket(bucketName);
        }
    }

    public List<Bucket> getAllBuckets() throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getMinioClient().listBuckets();
    }

    public Optional<Bucket> getBucket(String bucketName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getMinioClient().listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    public void removeBucket(String bucketName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        getMinioClient().removeBucket(bucketName);
    }

    public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) throws InvalidPortException, InvalidEndpointException {
        List objectList = new ArrayList();
        Iterable<Result<Item>> objectsIterator = getMinioClient().listObjects(bucketName, prefix, recursive);
        objectsIterator.forEach(i -> {
            try {
                objectList.add(new MinioItem(i.get()));
            } catch (Exception e) {
                new Exception(e);
            }
        });
        return objectList;
    }

    /**
     * Object operations
     */

    public String getObjectURL(String bucketName, String objectName, Integer expires) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidExpiresRangeException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getMinioClient().presignedGetObject(bucketName, objectName, expires);
    }

    public void saveObject(String bucketName, String objectName, InputStream stream, long size, String contentType) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidArgumentException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        getMinioClient().putObject(bucketName, objectName, stream, size, contentType);
    }

//    public void saveObject(String bucketName, String objectName, InputStream stream, long size, String contentType) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidArgumentException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
//        getMinioClient().putObject(bucketName, objectName, stream, size, contentType);
//    }

    public ObjectStat getObjectInfo(String bucketName, String objectName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return getMinioClient().statObject(bucketName, objectName);
    }

    public File getObject(String bucketName, String objectName ,String originName) throws IOException, NoSuchAlgorithmException, InvalidKeyException, XmlPullParserException {
        File file = new File(originName);
        try {
            OutputStream os = new FileOutputStream(file);
            getMinioClient().statObject(bucketName, objectName);

            // 获取"myobject"的输入流。
            InputStream stream = getMinioClient().getObject(bucketName, objectName);
            // 读取输入流直到EOF并打印到控制台。
            byte[] buf = new byte[16384];
            int bytesRead = 0;
            while ((bytesRead = stream.read(buf, 0, 8192)) != -1) {
                os.write(buf, 0, bytesRead);
            }
            os.close();
            // 关闭流,此处为示例,流关闭最好放在finally块。
            stream.close();
        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
        }
        return file;
    }

    public void removeObject(String bucketName, String objectName) throws InvalidPortException, InvalidEndpointException, IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException, InvalidArgumentException {
        getMinioClient().removeObject(bucketName, objectName);
    }


    /**
     * Gets a Minio client
     *
     * @return an authenticated Amazon S3 client
     */
    public MinioClient getMinioClient() throws InvalidPortException, InvalidEndpointException {
        return new MinioClient(endpoint, accessKey, secretKey);
    }
}

3.获取文件预览和下载地址

@GetMapping(value = "/getFilePresignedUrl")
    @ApiOperation(value = "获取文件浏览或下载预签地址", httpMethod = "Get", notes = "获取文件浏览或下载预签地址,有失效时间")
    public String getFilePresignedUrl(@RequestParam("bucketName") String bucketName,
                             @RequestParam("objectName") String objectName) throws Exception {
        log.info("获取文件浏览或下载预签地址,bucketName{},objectName{}",bucketName,objectName);
        return minioYunService.getFilePresignedUrl(bucketName,objectName);
    }


/**
     *  @author: xuyahui
     *  @Date: 2021/5/27 9:45
     *  @Description: 根据文件存储名称,获取文件浏览或下载预签地址
     */
    @Override
    public String getFilePresignedUrl(String bucketName, String objectName) {
        try {
            client = new MinioClient(constants.getEndpointViewUrl(), constants.getAccessKey(), constants.getSecretKey());
            boolean isExist = client.bucketExists(bucketName);
            if(isExist){
                return client.presignedGetObject(bucketName, objectName, constants.getExpiresTime());
            }
        } catch (Exception e) {
            log.error("get presigned url error" + e);
        }
        return "";
    }

五、本地写入文件

开发中,有些场景需要将文件写入到本地,再进行后续的操作,比如上传等,文件写入本地的时候,注意创建文件夹和文件的顺序。建议先创建文件夹,再创建文件,避免系统错误。

// 推荐的做法
String path =  RuoYiConfig.getUploadPath()+"\\mixstation\\"+uid+"\\"+projectId+".sdt";
        File file = new File(path);
        if (!file.exists()) {
            file.getParentFile().mkdirs();
        }
        file.createNewFile();


// 会出错的实现,windows server 2013 会提示文件目录不存在
String pathName = RuoYiConfig.getUploadPath()+"\\mixstation\\"+authorId+"\\"+projectId+".sdt";
        File file = new File(pathName);
        if (!file.exists()) {
            file.createNewFile();
        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 文件导入 Spring Boot提供了多种方式来实现文件导入,以下是其中一种方式: 1) 定义上传文件的接口: ``` @PostMapping("/upload") public ResponseEntity<String> upload(@RequestParam("file") MultipartFile file) { try { // Save the file to a temporary directory File tempFile = File.createTempFile("temp", file.getOriginalFilename()); file.transferTo(tempFile); // Process the file // ... return ResponseEntity.ok("File uploaded successfully"); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); } } ``` 2) 在前端页面中添加上传文件的表单: ``` <form method="post" enctype="multipart/form-data" action="/upload"> <input type="file" name="file"/> <button type="submit">Upload</button> </form> ``` 3) 在应用程序中添加文件上传的配置: ``` @Configuration public class FileUploadConfig { @Bean public MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); factory.setMaxFileSize(DataSize.ofMegabytes(10)); factory.setMaxRequestSize(DataSize.ofMegabytes(10)); return factory.createMultipartConfig(); } } ``` 2. 文件导出 Spring Boot也提供了多种方式来实现文件导出,以下是其中一种方式: 1) 定义文件导出的接口: ``` @GetMapping("/download") public ResponseEntity<Resource> download() { // Generate the file content String content = "Hello, world!"; ByteArrayResource resource = new ByteArrayResource(content.getBytes()); // Return the file as a downloadable resource return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=example.txt") .contentType(MediaType.TEXT_PLAIN) .contentLength(content.getBytes().length) .body(resource); } ``` 2) 在前端页面中添加下载文件的链接: ``` <a href="/download">Download</a> ``` 以上就是Spring Boot实现文件导入导出的简单示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值