基于Mongodb的文件上传下载,图片预览

1.依赖

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>
  <dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
          <groupId>org.mybatis.spring.boot</groupId>
          <artifactId>mybatis-spring-boot-starter</artifactId>
          <version>1.3.2</version>
      </dependency>
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
      </dependency>
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
      </dependency>
      <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger2</artifactId>
          <version>2.6.1</version>
      </dependency>
      <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger-ui</artifactId>
          <version>2.6.1</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid-spring-boot-starter</artifactId>
          <version>1.1.10</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.54</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-mongodb</artifactId>
      </dependency>
      <!--谷歌图片压缩组件-->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.8</version>
        </dependency>
  </dependencies>

2.配置文件

server.port=80
spring.aop.proxy-target-class=true
server.tomcat.uri-encoding=utf-8
spring.datasource.qy.name=qy
spring.datasource.qy.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.qy.url=jdbc\:mysql\://ip\:port/scm11?useUnicode\=true&characterEncoding\=utf-8&zeroDateTimeBehavior\=round&transformedBitIsBoolean\=true&useSSL\=false&allowMultiQueries\=true
spring.datasource.qy.username=root
spring.datasource.qy.password=password

spring.datasource.fqy.name=fqy
spring.datasource.fqy.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.fqy.url=jdbc\:mysql\://ip\:port/scm12?useUnicode\=true&characterEncoding\=utf-8&zeroDateTimeBehavior\=round&transformedBitIsBoolean\=true&useSSL\=false&allowMultiQueries\=true
spring.datasource.fqy.username=root
spring.datasource.fqy.password=password
#显示sql语句
spring.jpa.show-sql=true
spring.data.mongodb.uri=mongodb\://root\:sql666@ip\:port/admin
spring.data.mongodb.database=chenfan_photo_test
spring.servlet.multipart.max-file-size: 2048Mb
spring.servlet.multipart.max-request-size: 200Mb
spring.servlet.multipart.resolve-lazily: true

3.枚举类,返回体代码

public enum ResponseCode {
    /** 成功 */
    SUCCESS(200, "success"),
    /** 保存成功 */
    SAVE_SUCCESS(200, "保存成功"),
    /** 保存失败 */
    SAVE_ERROR(500, "保存失败"),
    /** 删除成功*/
    DELETE_SUCCESS(200, "删除成功"),
    /** 删除失败*/
    DELETE_ERROR(500, "删除失败"),
    /** 获取数据库连接失败 */
    NOT_FIND_DATABASE_CONN(401, "not find database conn"),
    LOGIN_SUCCESS(200, "登陆成功"),
    LOGIN_ERROR(401, "登陆失败"),
    LOGIN_EASY(500, "登陆密码过于简单"),
    PARAMETER_ERROR(403,"参数错误"),
    SAMPLE_STOCK_HANDOVER_ERROR(400,"此样衣正在转交中"),
    STOCKOUT_ERROR(400,"库存不足,请修改后提交");

    private final int code;
    private final String msg;

    ResponseCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}
public class Constant {

    /** 参数错误 */
    public static final int ERROR_PARAM_CODE = 400;
    /** 登陆错误 */
    public static final int UN_AUTHORIZED = 401;
    /** 操作失败 */
    public static final int FAIL = 401;
    /** 非预期性内部错误 */
    public static final int EXCEPTION = 500;
    /** 业务异常 */
    public static final int ERROR_BUSINESS_CODE = 501;
    /** 数据源类型 */
    public static final String DATA_TYPE = "dataType";
    /** 返回数据格式,json */
    public static final String CONTENT_TYPE = "application/json; charset=utf-8";
    /** user信息 */
    public static final String USER_INFO = "user_info";
    /** token */
    public static final String AUTHORIZATION_TOKEN = "Authorization";
    /** agent */
    public static final String USER_AGENT = "user_agent";
    /** user_session_id */
    public static final String USER_SESSION_ID = "uid";

    public static final String AUTHORIZATION = "userToken";

    public static final String HEADER_IP = "user_ip";

    public static final String ANDROID_AGENT = "Android";

    public static final String TOKEN_PIC_CODE = "verifyCodeToken";

    private Constant() {}
}
@ApiModel
@Data
public class Response<T> {

    /** 返回码 */
    @ApiModelProperty(position = 1, value = "返回码")
    private int code;
    /** 返回文字内容 */
    @ApiModelProperty(position = 2, value = "返回信息")
    private String message;
    /** 返回实体对象 */
    @ApiModelProperty(position = 3, value = "返回体")
    private T obj;

    public Response(int code, String message, T obj) {
        this.code = code;
        this.message = message;
        this.obj = obj;
    }

    public Response() {}

    public Response(Exception ex) {
        this.code = Constant.EXCEPTION;
        this.message = ex.getMessage();
    }

    public Response(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public Response(ResponseCode responseCode) {
        this.code = responseCode.getCode();
        this.message = responseCode.getMsg();
    }

    public Response(ResponseCode responseCode, T obj) {
        this.code = responseCode.getCode();
        this.message = responseCode.getMsg();
        this.obj = obj;
    }
}

4.文件上传

//文件上传的返回值
@Data
public class FileResult {
    private String fileName;
    private String id;
}
@RestController
@RequestMapping("file/")
@Slf4j
public class FileController {
    @Autowired
    private FileService fileService;

    @ApiOperation(value = "上传文件", notes = "上传文件")
    @PostMapping(value = "upload")
    public Response<Object> upload(MultipartHttpServletRequest request) {
        log.info("进入方法>>>--upload--上传文件");
        if (null != request) {
            List<FileResult> upload = null;
            try {
                upload = fileService.upload(request);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return new Response<>(Constant.EXCEPTION, e.getMessage());
            }
            log.info("退出方法>>>--upload--上传文件");
            return new Response<>(ResponseCode.SUCCESS, upload);
        }
        log.info("退出方法>>>--upload--上传文件");
        return new Response<>(Constant.FAIL, "上传文件不能为空");
    }
}
@Service
@Slf4j
public class FileService {
    @Autowired
    private FileMapper fileMapper;
    private static final String[] FILE_TYPES =
            new String[] {
                    "jpg", "bmp", "jpeg", "png", "gif", "tif", "pcx", "tga", "exif", "exif", "svg",
                    "psd", "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "WMF", "webp"
            };
    public List<FileResult> upload(MultipartHttpServletRequest request) {
        List<FileResult> result = new ArrayList<>();
        //拿到文件名
        Iterator<String> fileNames = request.getFileNames();
        while (fileNames.hasNext()) {
            FileResult fileResult = new FileResult();
            String fileName = fileNames.next();
            //根据文件名拿到文件
            MultipartFile file = request.getFile(fileName);
            //获取上传文件的原名
            String name = file.getOriginalFilename();
            String fileNameStr= Base64.encodeBase64String(name.getBytes());
            String[] split = name.split("\\.");
            //拿到文件后缀名
            String suff = split[split.length - 1];
            // 文件类型
            String contentType = file.getContentType();
            String save = "";
            try {
                save = fileMapper.save(file.getInputStream(), fileNameStr, contentType);
            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
            if (null != save) {
                fileResult.setFileName(name);
                fileResult.setId(save + "." + suff);
            }
            result.add(fileResult);
        }
        return result;
    }
}
@Component
public class FileMapper {
    @Autowired
    private  GridFsTemplate gridFsTemplate;
    public String save(InputStream file, String fileName, String contentType) {
        // 将文件存储到mongodb中,mongodb 将会返回这个文件的具体信息
        ObjectId store = gridFsTemplate.store(file, fileName, contentType);
        String id = store.toString();
        if (StringUtils.hasLength(id)) {
            return id;
        }
        return null;
    }
}

上传成功
在这里插入图片描述

5.文件下载

@ApiOperation(value = "下载文件", notes = "下载文件")
    @GetMapping(value = "download")
    public Response<Object> download(String fileId, HttpServletResponse response) {
        log.info("进入方法>>>--download--下载文件");
        if (!StringUtils.hasLength(fileId)) {
            return new Response<>(Constant.ERROR_PARAM_CODE, "文件ID不能为空");
        }
        String[] split = fileId.split("\\.");
        try {
            fileService.download(split[0], response);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return new Response<>(Constant.EXCEPTION, e.getMessage());
        }
        log.info("退出方法>>>--download--下载文件");
        return new Response<>(ResponseCode.SUCCESS);
    }
@Component
public class FileMapper {
    @Autowired
    private  GridFsTemplate gridFsTemplate;
    public String save(InputStream file, String fileName, String contentType) {
        // 将文件存储到mongodb中,mongodb 将会返回这个文件的具体信息
        ObjectId store = gridFsTemplate.store(file, fileName, contentType);
        String id = store.toString();
        if (StringUtils.hasLength(id)) {
            return id;
        }
        return null;
    }

    public GridFSFile find(String fileId) {
        return gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));
    }
}

public void download(String fileId, HttpServletResponse response) {
        if (!StringUtils.hasLength(fileId)) {
            throw new RuntimeException("ID不能为空");
        }
        GridFSFile file = fileMapper.find(fileId);
        if (null == file) {
            throw new RuntimeException("ID对应文件不存在");
        }
        String fileName = file.getFilename();
        String[] split = fileName.split("\\.");
        try {
            Long.parseLong(split[0]);
        } catch (Exception e) {
            fileName =
                    new String(
                            Base64.decodeBase64(fileName.getBytes(StandardCharsets.UTF_8)),
                            StandardCharsets.UTF_8);
        }
        //转成GridFsResource类取文件类型
        response.setContentType(mongoResource.convertGridFSFile2Resource(file).getContentType());
        response.setHeader("Content-Disposition", "attachment; filename=" +fileName);
        //文件长度
        response.setHeader("Content-Length", String.valueOf(file.getLength()));
        try {
            OutputStream out = response.getOutputStream();
            //IO复制
            InputStream in=mongoResource.convertGridFSFile2Resource(file).getInputStream();
            IOUtils.copy(
                    mongoResource.convertGridFSFile2Resource(file).getInputStream(), out);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        log.info("文件传输完成,退出方法");
    }

下载成功,切记不要用swagger接口去下载,会乱码
下载成功返回值为null,关闭outputstream后不能再返回值

6.图片查看

@ApiOperation(value = "读取图片--压缩", notes = "读取图片")
    @GetMapping(value = "views/{id}")
    public void viewsImg(
            @PathVariable String id, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        log.info("进入方法>>>--viewsImg--读取图片");
        if (id != null && !"null".equalsIgnoreCase(id)) {
            try {
                fileService.viewImg(id, request, response);
            } catch (IOException e) {
                log.error("读取图片文件失败", e.getMessage(), e);
                log.info("退出方法>>>--viewsImg--读取图片");
            }
            log.info("退出方法>>>--viewsImg--读取图片");
        } else {
            log.info("退出方法>>>--viewsImg--读取图片>没有文件id");
        }
    }
public void viewImg(String id, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 因为取出来的id带有后缀,因此做去除后缀处理
        if (id.contains(".")) {
            String[] split = id.split("\\.");
            id = split[0];
        }
        GridFSFile file = fileMapper.find(id);
        if (null == file) {
            throw new RuntimeException("ID对应文件不存在");
        }
        String fileName = file.getFilename();
        String[] split = fileName.split("\\.");
        try {
            Long.parseLong(split[0]);
        } catch (Exception e) {
            fileName =
                    new String(
                            Base64.decodeBase64(fileName.getBytes(StandardCharsets.UTF_8)),
                            StandardCharsets.UTF_8);
        }
        OutputStream out = response.getOutputStream();
        //取后缀
        String sub = fileName.substring(fileName.lastIndexOf(".") + 1);
        boolean flag = false;
        for (String fileType : FILE_TYPES) {
            if (sub.equalsIgnoreCase(fileType)) {
                flag = true;
                break;
            }
        }
        if (flag) {
            log.info("图片类型,进入预览");
            response.setHeader("Content-disposition", "inline; filename=" + fileName);
            response.setContentType("image/" + sub);
            // 不进行压缩的文件大小,单位为bit
            int notCompressionBit = 512000;
            //大于512000bit就压缩
            if (file.getLength() > notCompressionBit) {
                Thumbnails.of(mongoResource.convertGridFSFile2Resource(file).getInputStream())
                        .scale(0.2f)
                        .outputQuality(0.5f)
                        .toOutputStream(out);
            }
            out.flush();
            out.close();
        } else {
            log.info("非图片类型,进入下载");
            //转成GridFsResource类取文件类型
            response.setContentType(mongoResource.convertGridFSFile2Resource(file).getContentType());
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            //文件长度
            response.setHeader("Content-Length", String.valueOf(file.getLength()));
            try {
                //IO复制
                InputStream in = mongoResource.convertGridFSFile2Resource(file).getInputStream();
                IOUtils.copy(
                        mongoResource.convertGridFSFile2Resource(file).getInputStream(), out);
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }

在这里插入图片描述

7.批量下载压缩文件

@ApiOperation(value = "批量下载压缩文件", notes = "批量下载压缩文件")
    @GetMapping(value = "downloadToZip")
    public Response<Object> downloadToZip(
            String zipName,
            String fileIds,
            HttpServletRequest request,
            HttpServletResponse response) {
        log.info("进入方法>>>--downloadToZip--批量下载压缩文件");
        if (!StringUtils.hasLength(fileIds)) {
            return new Response<>(Constant.ERROR_PARAM_CODE, "文件ID不能为空");
        }
        try {
            fileService.downloadToZip(zipName, fileIds, request, response);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            log.info("退出方法>>>--downloadToZip--批量下载压缩文件");
            return new Response<>(Constant.EXCEPTION, e.getMessage());
        }
        log.info("退出方法>>>--downloadToZip--批量下载压缩文件");
        return new Response<>(ResponseCode.SUCCESS);
    }
public void downloadToZip(
            String zipName,
            String fileIds,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {
        //压缩包文件名
        zipName = new String(zipName.getBytes("ISO8859-1"), "UTF-8"); // 转换文件名,防止乱码
        // 获得请求头中的User-Agent
        String agent = request.getHeader("User-Agent");
        // 根据不同的客户端进行不同的编码
        if (agent.contains("MSIE")) {
            // IE浏览器
            zipName = URLEncoder.encode(zipName, "utf-8");
            zipName = zipName.replace("+", " ");
        } else if (agent.contains("Firefox")) {
            // 火狐浏览器
            BASE64Encoder base64Encoder = new BASE64Encoder();
            zipName = "=?utf-8?B?" + base64Encoder.encode(zipName.getBytes("utf-8")) + "?=";
        } else {
            // 其它浏览器
            zipName = URLEncoder.encode(zipName, "utf-8");
        }
        // 初始化信息
        response.setContentType("application/zip");
        response.setHeader("Content-disposition", "attachment; filename=" + zipName);
        ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
        // 获取文件信息
        String[] fileIdsArray = fileIds.split("\\;");
        for (int i = 0; i < fileIdsArray.length; i++) {
            String[] fileIdArray = fileIdsArray[i].split("\\.");
            if (!StringUtils.hasLength(fileIdArray[0])) {
                throw new RuntimeException("ID不能为空");
            }
            GridFSFile file = fileMapper.find(fileIdArray[0]);
            if (null == file) {
                throw new RuntimeException("ID对应文件不存在");
            }
            String fileName = file.getFilename();
            String[] split = fileName.split("\\.");
            try {
                Long.parseLong(split[0]);
            } catch (Exception e) {
                fileName =
                        new String(
                                Base64.decodeBase64(fileName.getBytes(StandardCharsets.UTF_8)),
                                StandardCharsets.UTF_8);
            }
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            IOUtils.copy(mongoResource.convertGridFSFile2Resource(file).getInputStream(), byteOut);
            byte[] data = byteOut.toByteArray();
            zipOut.putNextEntry(new ZipEntry(fileName));
            zipOut.write(data);
            zipOut.closeEntry();
            byteOut.close();
        }
        zipOut.flush();
        zipOut.close();
        log.info("文件传输完成,退出方法");
    }

在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值