若依框架如何实现文件上传与下载功能

2025-06发布2次浏览

若依框架(RuoYi)是一款基于Spring Boot和Spring Cloud的开源后台管理系统,其功能丰富且易于扩展。实现文件上传与下载功能是许多项目中的常见需求,下面将详细介绍如何在若依框架中实现这一功能。


1. 文件上传功能

1.1 前端实现

前端可以通过表单提交或使用FormData对象来发送文件数据。若依框架默认使用Vue.js作为前端框架,以下是一个简单的示例代码:

<template>
  <div>
    <el-upload
      class="upload-demo"
      action="/api/common/upload"
      :on-success="handleSuccess"
      :before-upload="beforeUpload">
      <el-button size="small" type="primary">点击上传</el-button>
    </el-upload>
  </div>
</template>

<script>
export default {
  methods: {
    handleSuccess(response, file, fileList) {
      this.$message.success("文件上传成功!");
    },
    beforeUpload(file) {
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isLt2M) {
        this.$message.error("上传文件大小不能超过 2MB!");
      }
      return isLt2M;
    }
  }
};
</script>
  • action属性指定了后端接口地址。
  • on-success回调函数用于处理上传成功后的逻辑。
  • before-upload钩子可以用来校验文件大小、类型等。

1.2 后端实现

在若依框架中,文件上传的核心逻辑位于com.ruoyi.common.controller.CommonController类中。以下是关键代码解析:

1.2.1 接口定义

@Log(title = "文件上传", businessType = BusinessType.UPLOAD)
@PostMapping("/upload")
public AjaxResult uploadFile(@RequestParam MultipartFile file) throws Exception {
    try {
        // 调用工具类方法保存文件
        String fileName = FileUploadUtils.upload(RuoYiConfig.getProfile(), file);
        String url = StringUtils.format("{}/{}", RuoYiConfig.getDomain(), fileName);
        return AjaxResult.success(url);
    } catch (Exception e) {
        return AjaxResult.error(e.getMessage());
    }
}

1.2.2 文件保存逻辑

FileUploadUtils工具类负责实际的文件保存操作:

public static final String UPLOAD_DIR = "upload";

public static String upload(String baseDir, MultipartFile file) throws IOException {
    try {
        // 验证文件是否为空
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        // 获取文件名和扩展名
        String fileName = file.getOriginalFilename();
        String extension = FilenameUtils.getExtension(fileName);

        // 检查文件类型是否合法
        if (!FileUploadUtils.isFileAllowed(extension)) {
            throw new FileSizeLimitExceededException(FileUploadUtils.DEFAULT_ALLOWED_EXTENSION);
        }

        // 构建目标路径
        String filePath = baseDir + "/" + UPLOAD_DIR + "/" + DateUtils.datePath() + "/";
        File desc = new File(filePath + UUID.randomUUID().toString() + "." + extension);

        // 如果目录不存在,则创建
        if (!desc.getParentFile().exists()) {
            desc.getParentFile().mkdirs();
        }

        // 保存文件
        file.transferTo(desc);
        returnStringUtils.substringAfterLast(desc.getAbsolutePath(), baseDir.replace("/", "\\"));
    } catch (Exception e) {
        throw new IOException("上传文件失败", e);
    }
}
  • baseDir:基础路径,通常从配置文件中读取。
  • DateUtils.datePath():生成按日期分隔的文件夹路径,避免文件过多导致性能问题。
  • UUID.randomUUID():为文件生成唯一标识符,防止文件名冲突。

2. 文件下载功能

2.1 前端实现

前端通过调用后端接口并触发浏览器下载行为即可完成文件下载。以下是一个示例代码:

downloadFile(url) {
  window.location.href = url;
}

或者使用axios进行更复杂的处理:

downloadFile(url) {
  axios({
    method: 'get',
    url: url,
    responseType: 'blob'
  }).then((response) => {
    const blob = new Blob([response.data]);
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'filename.ext'; // 自定义文件名
    link.click();
  });
}

2.2 后端实现

后端需要提供一个接口用于响应文件下载请求:

2.2.1 接口定义

@Log(title = "文件下载", businessType = BusinessType.DOWNLOAD)
@GetMapping("/download/{fileName:.+}")
public void download(HttpServletResponse response, @PathVariable String fileName) throws IOException {
    try {
        // 构建文件路径
        String filePath = RuoYiConfig.getProfile() + "/upload/" + fileName;

        // 检查文件是否存在
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException("文件未找到!");
        }

        // 设置响应头
        response.reset();
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
        response.setContentType("application/octet-stream");

        // 写入文件流
        FileInputStream inputStream = new FileInputStream(file);
        OutputStream outputStream = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) > 0) {
            outputStream.write(buffer, 0, len);
        }
        inputStream.close();
        outputStream.flush();
        outputStream.close();
    } catch (Exception e) {
        log.error("文件下载异常:{}", e.getMessage());
    }
}

3. 注意事项

  1. 文件存储路径:建议将文件存储在服务器上的独立目录中,并定期清理无用文件以节省磁盘空间。
  2. 安全性:对上传文件的类型和大小进行严格限制,防止恶意文件上传。
  3. 并发处理:对于大文件上传或高并发场景,可以考虑使用分片上传或异步处理机制。