第2-3-4章 上传附件的接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss

5.3 接口开发-上传附件

第2-1-2章 传统方式安装FastDFS-附FastDFS常用命令
第2-1-3章 docker-compose安装FastDFS,实现文件存储服务
第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料

全套代码及资料全部完整提供,点此处下载

5.3.1 接口文档

上传附件接口要完成的操作主要有两个:

  • 将客户端提交的文件上传到指定存储位置(具体存储位置由配置文件配置的存储策略确定)
  • 将上传的文件信息保存到数据库的pd_attachment表中

接口文档如下:
在这里插入图片描述
在这里插入图片描述

5.3.2 代码实现

第一步:创建AttachmentController并提供文件上传方法

package com.itheima.pinda.file.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.pinda.base.BaseController;
import com.itheima.pinda.base.R;
import com.itheima.pinda.file.dto.AttachmentDTO;
import com.itheima.pinda.file.dto.AttachmentRemoveDTO;
import com.itheima.pinda.file.dto.AttachmentResultDTO;
import com.itheima.pinda.file.dto.FilePageReqDTO;
import com.itheima.pinda.file.entity.Attachment;
import com.itheima.pinda.file.service.AttachmentService;
import com.itheima.pinda.utils.BizAssert;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import static com.itheima.pinda.exception.code.ExceptionCode.BASE_VALID_PARAM;
import static java.util.stream.Collectors.groupingBy;
/**
 * 附件处理控制器
 */
@RestController
@RequestMapping("/attachment")
@Slf4j
@Api(value = "附件", tags = "附件")
public class AttachmentController extends BaseController {
    @Autowired
    private AttachmentService attachmentService;

    /**
     * 上传附件
     */
    @ApiOperation(value = "附件上传", notes = "附件上传")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "isSingle", value = "是否单文件", dataType = "boolean", paramType = "query"),
            @ApiImplicitParam(name = "id", value = "文件id", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "bizId", value = "业务id", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "bizType", value = "业务类型", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "file", value = "附件", dataType = "MultipartFile", allowMultiple = true, required = true),
    })
    @PostMapping(value = "/upload")
    public R<AttachmentDTO> upload(
            @RequestParam(value = "file") MultipartFile file,
            @RequestParam(value = "isSingle", required = false, defaultValue = "false") Boolean isSingle,
            @RequestParam(value = "id", required = false) Long id,
            @RequestParam(value = "bizId", required = false) String bizId,
            @RequestParam(value = "bizType") String bizType) {
        
        // 忽略路径字段,只处理文件类型
        if (file.isEmpty()) {
            return fail(BASE_VALID_PARAM.build("请求中必须至少包含一个有效文件"));
        }
        AttachmentDTO attachment = attachmentService.upload(file, 
                                                            id, 
                                                            bizType, 
                                                            bizId, 
                                                            isSingle);

        return success(attachment);
    }
}

第二步:创建AttachmentService接口

package com.itheima.pinda.file.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.pinda.file.dto.AttachmentDTO;
import com.itheima.pinda.file.dto.AttachmentResultDTO;
import com.itheima.pinda.file.dto.FilePageReqDTO;
import com.itheima.pinda.file.entity.Attachment;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 附件业务接口
 */
public interface AttachmentService extends IService<Attachment> {
    /**
     * 上传附件
     *
     * @param file 文件
     * @param id 附件id
     * @param bizType 业务类型
     * @param bizId 业务id
     * @param isSingle 是否单个文件
     * @return
     */
    AttachmentDTO upload(MultipartFile file, Long id, String bizType, 
                         String bizId, Boolean isSingle);

}

第三步:创建AttachmentServiceImpl实现类

package com.itheima.pinda.file.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.pinda.base.id.IdGenerate;
import com.itheima.pinda.database.mybatis.conditions.Wraps;
import com.itheima.pinda.database.mybatis.conditions.query.LbqWrapper;
import com.itheima.pinda.dozer.DozerUtils;
import com.itheima.pinda.exception.BizException;
import com.itheima.pinda.file.dao.AttachmentMapper;
import com.itheima.pinda.file.domain.FileDO;
import com.itheima.pinda.file.domain.FileDeleteDO;
import com.itheima.pinda.file.dto.AttachmentDTO;
import com.itheima.pinda.file.dto.AttachmentResultDTO;
import com.itheima.pinda.file.dto.FilePageReqDTO;
import com.itheima.pinda.file.entity.Attachment;
import com.itheima.pinda.file.entity.File;
import com.itheima.pinda.file.enumeration.DataType;
import com.itheima.pinda.file.properties.FileServerProperties;
import com.itheima.pinda.file.service.AttachmentService;
import com.itheima.pinda.file.strategy.FileStrategy;
import com.itheima.pinda.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 附件业务实现类
 */
@Slf4j
@Service
public class AttachmentServiceImpl extends ServiceImpl<AttachmentMapper, Attachment> implements AttachmentService {
    @Autowired
    private IdGenerate<Long> idGenerate;
    @Autowired
    private DozerUtils dozer;
    @Autowired
    private FileStrategy fileStrategy;
    @Autowired
    private FileServerProperties fileProperties;

    /**
     * 上传附件
     *
     * @param multipartFile 文件
     * @param id 附件id
     * @param bizType 业务类型
     * @param bizId 业务id
     * @param isSingle 是否单个文件
     * @return
     */
    @Override
    public AttachmentDTO upload(MultipartFile multipartFile, Long id, String bizType, String bizId, Boolean isSingle) {
        //根据业务类型来判断是否生成业务id
        if (StringUtils.isNotEmpty(bizType) && StringUtils.isEmpty(bizId)) {
            bizId = String.valueOf(idGenerate.generate());
        }
        File file = fileStrategy.upload(multipartFile);

        Attachment attachment = dozer.map(file, Attachment.class);

        attachment.setBizId(bizId);
        attachment.setBizType(bizType);
        setDate(attachment);

        if (isSingle) {
            super.remove(Wraps.<Attachment>lbQ().eq(Attachment::getBizId, bizId).eq(Attachment::getBizType, bizType));
        }

        if (id != null && id > 0) {
            //当前端传递了文件id时,修改这条记录
            attachment.setId(id);
            super.updateById(attachment);
        } else {
            attachment.setId(idGenerate.generate());
            super.save(attachment);
        }

        AttachmentDTO dto = dozer.map(attachment, AttachmentDTO.class);
        return dto;
    }

    private void setDate(Attachment file) {
        LocalDateTime now = LocalDateTime.now();
        file.setCreateMonth(DateUtils.formatAsYearMonthEn(now));
        file.setCreateWeek(DateUtils.formatAsYearWeekEn(now));
        file.setCreateDay(DateUtils.formatAsDateEn(now));
    }
}

5.3.3 接口测试

第一步:启动Nacos配置中心,pd-file-server.yml配置内容如下:

pinda:
  mysql:
    database: pd_files
  nginx:
    ip: ${spring.cloud.client.ip-address} #正式环境要将该ip设置成nginx对应的公网ip
    port: 10000  #正式环境需要将该ip设置成nginx对应的公网端口
  swagger:
    enabled: true
    docket:
      file:
        title: 文件服务
        base-package: com.itheima.pinda.file.controller

  file:
    type: LOCAL # LOCAL ALI MINIO FAST_DFS  
    local:
      uriPrefix: http://${pinda.nginx.ip}:${pinda.nginx.port}
      bucket-name: oss-file-service
      endpoint: D:\soft\nginx-1.23.0\uploadFiles
    ali:
      # 请填写自己的阿里云存储配置
      bucket-name: bladex-loan
      endpoint: http://oss-cn-qingdao.aliyuncs.com
      access-key-id: LTAI4FhtimFAiz6iLGJSiJui  
      access-key-secret: SsU15qaPwpF1x5xMqwc0XzGuY92fnc

#FAST_DFS配置
fdfs:
  soTimeout: 1500
  connectTimeout: 600
  thumb-image:
    width: 150
    height: 150
  tracker-list:
    - 111.231.76.210:22122
  pool:
    #从池中借出的对象的最大数目
    max-total: 153
    max-wait-millis: 102
    jmx-name-base: 1
    jmx-name-prefix: 1


server:
  port: 8765

第二步:启动Nginx服务

第三步:启动文件服务

第四步:访问接口文档,地址为http://localhost:8765/doc.html

在这里插入图片描述

可以看到上传的文件已经保存到了本地磁盘:
在这里插入图片描述
同时上传的文件信息也已经保存到了pd_attachment表中:
在这里插入图片描述

可以通过Nginx提供的Http服务来访问上传的文件:

http://192.168.137.3:10000//oss-file-service/2022/11/e76d3505-df38-4f95-a7bd-fb5de3ebe923.txt

全套代码及资料全部完整提供,点此处下载

posted @ 2022-11-17 07:43  假装文艺范儿  阅读(408)  评论(0编辑  收藏  举报