使用ant-design-vue+FastDFS实现文件上传

一、上传页面代码

 <div class="clearfix">
            <a-upload
              :action="action"
              listType="picture-card"
              :fileList="fileList"
              @change="handleUploadChange"
              :customRequest="customRequest"
            >
              <div v-if="fileList.length < 1">
                <a-icon type="plus" />
                <div class="ant-upload-text">Uploaddiv>
              div>
            a-upload>
          div>

这里使用customRequest实现自定义上传,会覆盖自带的action选项

二、相关data模型

data() {
    return {
      avatarUrl: "http://" + this.$store.state.user.user.avatar,//获取用户头像地址
      action: "http://localhost:10011/weblog_upload/upload/image",//被覆盖掉了,不会起作用
      fileList: [],//上传的文件集合
    };
  },
  created() {
    this.fileList = [];
  },

三、自定义上传实现

/**
     * 自定义上传
     */
    customRequest(data) {
      var formData = new FormData();
      formData.append("file", data.file);
      this.saveFile(formData, data.file.name);
    },
    saveFile(formData, filename) {
      let that = this;
      that.fileList.length = 0;
      uploadApi
        .upload(formData)
        .then(resp => {
          if (resp.data.flag) {
            const file = {};
            file.uid = -2;
            file.name = filename;
            file.thumbUrl = "http://" + resp.data.data; //后台返回的缩略图地址
            that.fileList.push(file);//加入到fileList
            
            this.$store.dispatch("GetUserInfo").then(resp => {});//重新加载当前用户信息()
            //刷新页面(这里可以使用provice和inject结合的方式,但不知道为啥不起作用,所以用了一下方法,先跳转到一个空路由,再返回实现刷新效果)
            let NewPage = "_empty" + "?time=" + new Date().getTime() / 500;
            this.$router.push(NewPage);
            this.$router.go(-1);

            this.$message.success(resp.data.message);
          } else {
            this.$message.error(resp.data.message);
          }
        })
    },

三、后台使用FastDFS实现

3.1 导入依赖

 <dependencies>
        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.weblog</groupId>
            <artifactId>weblog_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

    </dependencies>

3.2 yml配置

weblog: #自定义FastDFS相关信息
  upload:
    baseUrl: 自己的fastDFS的地址
    allowTypes:
      - image/jpeg
      - image/png
      - image/bmp
      - image/jpg
fdfs:
  so-timeout: 1501 #超时时间
  connect-timeout: 601 #连接超时时间
  thumb-image:
    width: 100 # 缩略图
    height: 100
  tracker-list: #tracker地址
    - 自己的tracker地址,可写多个

3.3fdfs的配置类

/**
 * @author
 * @date 2019/10/2316:28
 */
@Configuration
@Import(FdfsClientConfig.class)
//解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastClientConfiguration {
}

3.4编写读取自定义配置信息的类

@Data
@ConfigurationProperties(prefix = "weblog.upload")
public class UploadProperties {
    private String baseUrl;
    private List<String> allowType;
}

3.5 UploadController

 @Autowired
    private UploadService uploadService;
    /**
     * 上传图片
     * @param file
     * @return
     */
    @PostMapping(value = "/image",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Result uploadImage(@RequestParam("file")MultipartFile file){
        try {
            String url = uploadService.uploadImage(file);
            return new Result(true, StatusCode.OK,"上传成功",url);
        }catch (Exception e){
            return new Result(false,StatusCode.ERROR,"上传出错");
        }

    }
}

注意:

在返回结果的时候,Result对象变为了XML格式

解决:

在PostMapping中添加produces=MediaType.APPLICATION_JSON_UTF8_VALUE
如:
produces = MediaType.APPLICATION_JSON_UTF8_VALUE

参考:https://blog.csdn.net/zyb2017/article/details/80265070

3.6 UploadService

3.6.1 注入相关依赖
@Service
@EnableConfigurationProperties(UploadProperties.class)
@Slf4j
public class UploadService {

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private UserClient userClient;

    @Autowired
    private HttpServletRequest request;

    /**
     * yml中的配置信息
     */
    @Autowired
    private UploadProperties uploadProperties;

    /**
     * 获取缩略图
     */
    @Autowired
    private ThumbImageConfig thumbImageConfig;

    private static final Logger  LOGGER  =LoggerFactory.getLogger(UploadService.class);
    /**
    * 允许的上传类型
    */
    private static final List<String> ALLOW_TYPES= Arrays.asList("image/jpg","image/jpeg","image/jpg","image/png","image/bmp");
  
}

6.2 图片上传实现

 /**
     * 上传头像(保存缩略图)
     * @param file
     * @return
     */
    public String uploadImage(MultipartFile file) {

        String originalFileName=file.getOriginalFilename();
        try {
            //校验文件类型
            String contentType = file.getContentType();
            if(!ALLOW_TYPES.contains(contentType)){
                LOGGER.info("文件内容不合法:{}",originalFileName);
                throw new MyException(ExceptionEnum.INVALID_FILE_TYPE);
            }
            //校验文件内容
            BufferedImage image = ImageIO.read(file.getInputStream());
            if(image==null){
                throw new MyException(ExceptionEnum.INVALID_FILE_TYPE);
            }
            /**
             * 先删除原来的头像
             */
            String userId= (String) request.getAttribute("id");
            Result result = userClient.findAvatarById(userId);
            String oldAvatar = (String) result.getData();
            
            //删除旧头像这部分可以提取出来,使用异步方法执行
            if(oldAvatar!=null&&!"".equals(oldAvatar)){
                //删除旧的头像地址
                storageClient.deleteFile(oldAvatar);
                String fullPath = StringUtils.substringBeforeLast(oldAvatar, "_")+"."+StringUtils.substringAfterLast(oldAvatar,".");
                storageClient.deleteFile(fullPath);
            }

            //上传到FastDFS
            String extension=StringUtils.substringAfterLast(file.getOriginalFilename(),".");
            StorePath storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(), extension, null);

            //修改数据库头像地址
            userClient.uploadAvatar(uploadProperties.getBaseUrl()+thumbImageConfig.getThumbImagePath(storePath.getFullPath()));
            //返回路径
            return uploadProperties.getBaseUrl()+thumbImageConfig.getThumbImagePath(storePath.getFullPath());
        } catch (IOException e) {
            //上传失败
            LOGGER.error("[文件上传]上传文件失败!",e);
            throw new MyException(ExceptionEnum.UPLOAD_FILE_ERROR);
        }
     
    }
说明:
  1. 因上传缩略图时,也会将非缩略图上传上去,所以删除时需要将两个都删除
 				//删除旧的头像地址(缩略图)
                storageClient.deleteFile(oldAvatar);
                //非缩略图地址
                String fullPath = StringUtils.substringBeforeLast(oldAvatar, "_")+"."+StringUtils.substringAfterLast(oldAvatar,".");
                storageClient.deleteFile(fullPath);

2.上传缩略图使用 storageClient.uploadImageAndCrtThumbImage方法

3.getFullPath返回带组的路径,getPath返回的路径不带组

你可能感兴趣的:(java)