【Java】文件上传及下载、限制文件大小

59 篇文章 0 订阅
18 篇文章 2 订阅

1、后端部分

      Controller代码

    // 上传
    @PostMapping("upload")
    @ResponseBody
    public Result upload(MultipartFile files, Integer id, String type){
        fileService.upload(files, id, type);
        return success().setRet(0);
    }

    // 下载
    @GetMapping("download")
    @ResponseBody
    public void download(HttpServletResponse response, Integer id){
        fileService.download(response, id);
    }

      Service代码

    @Value("${fileServer.storeDir}")
    private String storeDir;

    @Autowired
    private FileMapper fileMapper;

    @Override
    public void upload(MultipartFile file, Integer id, String type) {
        logger.info("文件关联id:{}, 文件名:{}", id, file.getOriginalFilename());
        logger.info("文件后缀名:{}", file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
        if(!file.isEmpty()){
            String dir = getStoreDir();

            File tempFile = new File(dir + System.currentTimeMillis() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
            try {
                file.transferTo(tempFile);

                FileInfo fileInfo = new FileInfo()
                        .setName(file.getOriginalFilename())
                        .setPath(tempFile.getAbsolutePath())
                        .setSize(tempFile.length())
                        .setTarget(id)
                        .setCreateDate(new Date())
                        .setMd5(FileUtil.md5(tempFile))
                        .setType(type);
                fileMapper.insert(fileInfo);

            } catch (IOException e) {
                logger.error(e.getMessage(), e);
                throw new InternalServerException("file build error");
            }
        }
    }


    @Override
    public void download(HttpServletResponse response, Integer id) {
        FileInfo fileInfo = fileMapper.findFileById(id);
        logger.info("下载文件名:{}", fileInfo.getName());
        File file = new File(fileInfo.getPath());

        if (!FileUtil.isExistingFile(file)) {
            throw new ResourceNotFoundException("file not found");
        }
        try (OutputStream outputStream = response.getOutputStream();
             InputStream inputStream = new FileInputStream(file)) {

            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileInfo.getName(), "UTF-8"));

            FileCopyUtils.copy(inputStream, outputStream);

        } catch (IOException e) {
            logger.error("下载文件失败!",e);
            throw new RemoteServiceUnavailableException("file download error");
        }
    }

    private String getStoreDir(){
        String dir = storeDir + File.separator ;
//        String dir = storeDir + File.separator + System.currentTimeMillis() + File.separator;
        try {
            FileUtil.mkdir(dir);
        } catch (IOException e) {
            logger.error("获取存储目录失败!",e);
            throw new InternalServerException("file build error");
        }
        return dir;
    }

    private void delFile(String path){
        try {
            FileUtil.delete(path);
        } catch (IOException e) {
            logger.error("删除文件失败!",e);
            throw new InternalServerException("file delete error");
        }

    }

      在application.yml配置文件中设置文件存储路径(这里假设是本地的E:\ptms中)、以及限制上传文件大小(这里设置为40M)。

# 应用名称
spring:
  application:
    name: ptms
  resources:
    static-locations: classpath:/static
    cache:
      period: PT1M        # 60 SECONDS
  servlet:
    multipart:
      max-file-size: 40Mb
      max-request-size: 40Mb

fileServer:
  storeDir: E:\ptms

2、前端部分

      前端代码如下,只看核心的上传下载即可。上传的控件采用element的el-upload控件,下载采用的是window.location.href。同时,在表单验证完之后,提交表单之前,还做了文件大小的校验,采用的是遍历this.$refs.upload.uploadFiles。

<template>
  <div>
    <el-form class="mt10 pd10 elForm" :rules="rules" ref="ruleForm" :model="ruleForm" label-width="130px" :label-position="labelPosition">
      <el-form-item label="项目名称:" prop="name" :inline-message="true">
        <el-col :span="8">
          <el-input placeholder="请输入项目名称" v-model="ruleForm.name"></el-input>
        </el-col>
      </el-form-item>
      <el-form-item label="项目版本:" prop="version">
        <el-col :span="8">
          <el-input placeholder="请输入项目版本" v-model="ruleForm.version"></el-input>
        </el-col>
      </el-form-item>
      <el-form-item label="产品系列:" prop="productSeriesId">
        <el-col :span="8">
          <el-select v-model="ruleForm.productSeriesId" placeholder="请选择产品系列" @change="chooseProductSeries" filterable clearable size="medium">
            <el-option v-for="item in productSeries" :key="item.id" :label="item.name" :value="item.id"></el-option>
          </el-select>
        </el-col>
      </el-form-item>
      <el-form-item label="项目起止:" prop="date1">
          <el-date-picker v-model="ruleForm.date1" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd">
          </el-date-picker>
      </el-form-item>
      <el-form-item label="项目描述:" prop="description">
        <el-col :span="8">
          <el-input placeholder="请输入项目描述" v-model="ruleForm.description" type="textarea"></el-input>
        </el-col>
      </el-form-item>
      <el-form-item label="操作备注:" v-if="this.$route.params.id != null">
        <el-col :span="8">
          <el-input placeholder="请输入操作备注" v-model="ruleForm.remark" type="textarea"></el-input>
        </el-col>
      </el-form-item>
      <el-form-item label="已上传附件:" v-if="fileUploaded">
        <el-col :span="11">
          <template>
            <el-table :data="tableData" border>
              <el-table-column prop="id" label="文件id" v-if="false"></el-table-column>
              <el-table-column prop="name" label="文件名称" min-width="180" show-overflow-tooltip>
                <template slot-scope="scope">
                  <a href="javascript:" @click="downloadFile(scope.row.id)" class="aLink">{{scope.row.name}}</a>
                </template>
              </el-table-column>
              <el-table-column prop="size" label="文件大小" min-width="100" show-overflow-tooltip></el-table-column>
              <el-table-column prop="createDate" label="上传时间" min-width="120" show-overflow-tooltip></el-table-column>
              <el-table-column label="操作" min-width="100" show-overflow-tooltip>
                <template slot-scope="scope">
                  <el-button type="text" @click="downloadFile(scope.row.id)">下载</el-button>
                  <el-button type="text" @click="deleteFile(scope.row.id)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-col>
      </el-form-item>
      <el-form-item label="附件上传:">
        <el-col :span="8">
          <el-upload class="upload-demo" ref="upload" name="files" :data="uploadData" action="/ptms/api/v1/File/upload" multiple
            :on-preview="handlePreview" :on-remove="handleRemove" :on-success="handleSuccess" :on-error="handleError" :auto-upload="false">
            <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
            <span slot="tip" class="el-upload__tip" style="margin-left: 20px; font-weight: bold">单个文件大小不超过{{maxFileSize}}}M</span>
          </el-upload>
        </el-col>
      </el-form-item>
      <el-form-item>
        <template slot-scope="scope">
          <el-button type="primary" @click="submit('ruleForm')" class="btn-min-w">提交</el-button>
          <el-button @click="cancel()"  class="btn-min-w">返回</el-button>
        </template>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
  import tableOperation from '@/components/layout/tableOperation'
  import  * as api from '@/api/ptms'
  import {tips} from '../../static/js/global.js'
  import moment from 'moment'
  export default {
    inject:['reload'],
    components:{ tableOperation},
    data(){
      return{
        labelPosition: 'right',
        ruleForm: {
          name:'',
          version:'',
          description:'',
          productSeriesId: '',
          date1: [],
          createdBy: sessionStorage.getItem("userId"),
          actor: sessionStorage.getItem("username"),
          remark: '',
        },
        productSeries: [],
        rules: {
          name: [
            { required: true, message: '请输入项目名称', trigger: 'blur' }
          ],
        },
        uploadData:{
          id: null,
          type: 'project'
        },
        id: null,
        tableData: [{}],
        fileUploaded: false,
        maxFileSize: 40,
      }
    },
    created() {
      // 跳转页面获取信息
      api.projectForm({id: this.$route.params.id})
        .then((res)=>{
          if(res.ret > -1){
            console.log(res.data)
            this.productSeries = res.data.productSeries;
             if(this.$route.params.id != null){
              this.ruleForm.name = res.data.project.name;
              this.ruleForm.version = res.data.project.version;
              this.ruleForm.description = res.data.project.description;
              this.ruleForm.productSeriesId = res.data.project.productSeriesId;
              this.ruleForm.createdBy = res.data.project.createdBy;
              if(res.data.project.startTime != null){
                this.ruleForm.date1.push(new Date(res.data.project.startTime));
              }
              if(res.data.project.endTime != null){
                this.ruleForm.date1.push(new Date(res.data.project.endTime));
              }

              this.id = this.$route.params.id;

              this.showFileList(this.id);
            }
          }
        })
    },
    methods:{

      chooseProductSeries(val){
        this.ruleForm.productSeriesId = val;
      },

      // 添加、修改项目
      submit(formName) {
        this.$refs[formName].validate((valid) => {
          if(valid){
            //文件大小校验
            let flag = true;
            this.$refs.upload.uploadFiles.map((item) => {
              if(item.size / 1024 / 1024 > this.maxFileSize){
                tips(this, item.name + '超过允许文件大小' + this.maxFileSize + 'M,请重新选择!', 'warning');
                flag = false;
              }
            });
            if(flag){
              const id = (typeof (this.$route.params.id) === 'undefined') ? null : this.$route.params.id;
              let startTime = null;
              let endTime = null;
              if(this.ruleForm.date1 != null && this.ruleForm.date1.length > 1){
                if(typeof this.ruleForm.date1[0] === 'object'){
                  startTime = moment(this.ruleForm.date1[0]).format("YYYY-MM-DD");
                  endTime = moment(this.ruleForm.date1[1]).format("YYYY-MM-DD");
                }else{
                  startTime = this.ruleForm.date1[0];
                  endTime = this.ruleForm.date1[1];
                }
              }

              api.projectFormAction({id: id, name: this.ruleForm.name, version: this.ruleForm.version, createdBy: this.ruleForm.createdBy,
                productSeriesId: this.ruleForm.productSeriesId, description:this.ruleForm.description, startTime: startTime,
                endTime:endTime, actor: this.ruleForm.actor, remark: this.ruleForm.remark})
                .then((res)=>{
                  console.log("项目信息", res.data)
                  if(res.data === "existed"){
                    tips(this, '该项目名称已存在', 'warning');
                    return;
                  }
                  //上传文件
                  if(this.$refs.upload.uploadFiles.length > 0){
                    this.uploadData.id = res.data;
                    this.submitUpload();
                  }else {
                    tips(this, this.id == null ? '添加成功!' :'修改成功!', 'success');
                    this.$router.push('/projectList');
                  }

                })

            }
          }
        })
      },

      // 下载文件
      downloadFile(val){
        window.location.href = "/ptms/api/v1/File/download?id=" + val;
      },

      // 删除文件
      deleteFile(val){
        this.$confirm('确认删除该附件?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          api.deleteFile({id: val})
            .then((res) => {
              if(res.ret === 0){
                tips(this, '附件删除成功!', 'success');
                this.showFileList(this.id);
                // this.reload();
              }
            })
        }).catch(() =>{
          // 取消
        });
      },

      // 展示已上传文件列表
      showFileList(id){
        api.getFilesByTarget({target: id, type: this.uploadData.type})
          .then((res) => {
            if(res.data.files.length > 0){
              this.fileUploaded = true;
              res.data.files.forEach((item) => {
                item.size = (item.size / 1024 ).toFixed(2) + " KB";
                item.createDate = moment(item.createDate).format('YYYY-MM-DD HH:mm:ss');
              });
              this.tableData = res.data.files;
            }else {
              this.fileUploaded = false;
            }
          })
      },

      handleSuccess(response, file, fileList){
        console.log("successFile: ", file);
        if(response.ret < 0){
          console.log("response: ", response);
          this.$refs.upload.clearFiles();
          tips(this, '上传失败!', 'error');
        }else {
          tips(this, this.id == null ? '添加成功!' :'修改成功!', 'success');
          this.$router.push('/projectList');
        }
      },

      handleError(err, file, fileList){
        console.log("err: ", err);
        console.log("errorFile: ", file);
        tips(this, '上传失败!', 'error');
      },

      submitUpload() {
        this.$refs.upload.submit();
      },

      handleRemove(file, fileList) {
        console.log(file, fileList);
      },

      handlePreview(file) {
        console.log(file);
      },

      // 取消返回上一页
      cancel() {
        this.$router.back(-1);
      }

    }
  }
</script>
<style lang="scss" scoped>
</style>


3、最终效果如下

 

  • 9
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值