文件打包上传与文件下载工具类,zip打包上传,上传后自动解压到服务器,路径需要拼接

3 篇文章 0 订阅

项目中用到了一个文件模板的上传,百度了一阵后自己写了个工具类实现了,记录下来以后可能用到,文件打包上传与文件下载工具类,zip打包上传,上传后自动解压到服务器,但路径需要自己拼接。 


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * @author modify by Jintao
 */
public class CompressUtil {

    /**
     * zip文件压缩
     *
     * @param inputFile  待压缩文件夹/文件名
     * @param outputFile 生成的压缩包名字
     */
    public static void zipCompress(String inputFile, String outputFile) throws IOException {
        //创建zip输出流
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputFile));
        //创建缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(out);
        File input = new File(inputFile);
        compress(out, bos, input, null);
        bos.close();
        out.close();
    }

    /**
     * 递归压缩
     *
     * @param name 压缩文件名,可以写为null保持默认
     */
    private static void compress(ZipOutputStream out, BufferedOutputStream bos, File input, String name) throws IOException {
        if (name == null) {
            name = input.getName();
            System.out.println("输入文件名:"+input.getName());
        }
        //如果路径为目录(文件夹)
        if (input.isDirectory()) {
            //取出文件夹中的文件(或子文件夹)
            File[] fList = input.listFiles();
            if (fList != null) {
                if (fList.length == 0) {
                    //如果文件夹为空,则只需在目的地zip文件中写入一个目录进入
                    out.putNextEntry(new ZipEntry(name + "/"));
                } else {
                    //如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
                    for (File file : fList) {
                        compress(out, bos, file, name + "/" + file.getName());
                    }
                }
            }
        } else {
            //如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中
            out.putNextEntry(new ZipEntry(name));
            FileInputStream fos = new FileInputStream(input);
            BufferedInputStream bis = new BufferedInputStream(fos);
            int len;
            //将源文件写入到zip文件中
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1) {
                out.write(buf, 0, len);
            }
            bis.close();
            fos.close();
        }
    }

    /**
     * zip压缩文 解压
     *
     * @param path 压缩文件的完整路径,如:f://test.zip
     */
    public static void deCompress(String path) throws IOException {
        File file = new File(path);
        String toPath = file.getParent() + "/decompressFiles";
        File createPath = new File(file.getParent(), "/decompressFiles");
        if (createPath.exists()) {
            deleteFilesDir(createPath);
            System.out.println("----已经存在先删除目录:" + toPath);
        }
        boolean mkdirp = createPath.mkdirs();
        System.out.println(mkdirp + "----成功创建目录:" + toPath);
        zipDecompress(path, toPath);
    }

    public static void deleteFilesDir(File deleteFile) {
        if (!deleteFile.exists()) {
            return;
        }
        if (deleteFile.isFile()) {
            String path = deleteFile.getPath();
            boolean delete = deleteFile.delete();
            System.out.println(delete + "----删除文件:" + path);
            return;
        }
        File[] files = deleteFile.listFiles();
        if (files != null) {
            for (File file : files) {
                deleteFilesDir(file);
            }
        }
        String path = deleteFile.getPath();
        boolean delete = deleteFile.delete();
        System.out.println(delete + "----删除目录:" + path);
    }

    /**
     * zip文件解压
     *
     * @param inputFile   待解压文件夹/文件
     * @param destDirPath 解压路径
     */
    private static void zipDecompress(String inputFile, String destDirPath) throws IOException {
        //获取当前压缩文件
        File srcFile = new File(inputFile);
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new IOException(srcFile.getPath() + "所指文件不存在");
        }
        //创建压缩文件对象
        ZipFile zipFile = new ZipFile(srcFile, Charset.forName("GBK"));
        //开始解压
        Enumeration<?> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            // 如果是文件夹,就创建个文件夹
            if (entry.isDirectory()) {
                String dirPath = destDirPath + "/" + entry.getName();
                boolean mkdirp = srcFile.mkdirs();
                System.out.println(mkdirp + "创建目录:" + dirPath);
            } else {
                // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                File targetFile = new File(destDirPath + "/" + entry.getName());
                // 保证这个文件的父文件夹必须要存在
                if (!targetFile.getParentFile().exists()) {
                    boolean madeira = targetFile.getParentFile().mkdirs();
                    System.out.println(madeira + "父目录:" + destDirPath + "/" + entry.getName());
                }
                boolean newFile = targetFile.createNewFile();
                System.out.println(newFile + "创建文件:" + destDirPath + "/" + entry.getName());
                // 将压缩文件内容写入到这个文件中
                InputStream is = zipFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(targetFile);
                int len;
                byte[] buf = new byte[1024];
                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                }
                // 关流顺序,先打开的后关闭
                fos.close();
                is.close();
            }
        }
    }

}

使用实例:


import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Controller
@RequestMapping("/template")
public class TemplateController extends BaseController {
    
    @Resource
    private TemplateAS templateAS;

    private String uploadPath="/home/template/";

    /**
     * 保存
     */
    @RequestMapping(value = "/save/{fileUploadFlg}/{actionType}", method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseDto doSave(HttpServletRequest request,
                              @Valid @RequestBody TemplateDto templateDto,
                              @PathVariable() String actionType,
                              @PathVariable() String fileUploadFlg,
                              BindingResult result) {
        // 返回值
        ResponseDto ret = new ResponseDto();
        // 继承的BaseController中的方法,分析附带的请求是否存在异常
        analysisBindResult(request, result);
        // 框架继承的类转换,相当于BeanUtils的复制属性
        Template template = BeanMapper.map(templateDto, Template.class);
        // 判断操作类型:新增or更新
        if ("add".equals(actionType)) {
            template.setTemplateCode(StringUtils.isEmpty(template.getTemplateCode()) ? getTemplateCode() : template.getTemplateCode());
            template.setIsDelete(YesOrNoConstants.NO);
            dealUser(template, request, actionType);
            templateAS.create(template);
        } else if ("update".equals(actionType)) {
            dealUser(template, request, actionType);
            templateAS.updateById(template);
        }
        if ("upload".equals(fileUploadFlg)) {
            // 解压缩文件
            try {
                String path = getPath(template);
                CompressUtil.deCompress(path);
            } catch (IOException e) {
                e.printStackTrace();
                ret.setCode(ResultCodeEnum.FAIL.getCode());
                ret.setMessage(e.getMessage());
                return ret;
            }
        }
        ret.setCode(ResultCodeEnum.SUCCESS.getCode());
        ret.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return ret;
    }

    /**
     * 上传文件
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public void uploadPackage(TemplateDto templateDto, @RequestParam("file") MultipartFile file, HttpServletResponse response) throws Exception {
        Map<String, Object> map = new HashMap<>(30);
        PrintWriter writer;
        // 虚拟文件名,uuid
        String virtualFileName = getVirtualFileName();
        // 模板文件编码
        String codePath = StringUtils.isEmpty(templateDto.getTemplateCode()) ? "default" : templateDto.getTemplateCode();
        String filePath = uploadPath + codePath + "/" + virtualFileName;
        File createPath = new File(uploadPath, codePath);
        // 校验目录是否存在,因首次服务器可能不存在对应目录,需创建目录
        if (!createPath.exists()) {
            boolean mkdirp = createPath.mkdirs();
            System.out.println(mkdirp + "--成功创建目录:" + filePath);
        }
        try {
            // 转存文件,Spring的MultipartFile类中transferTo方法实现了文件存储过程
            file.transferTo(new File(filePath));
            // 返回相应信息
            map.put("url", filePath);
            String realName = file.getOriginalFilename();
            map.put("fileName", realName != null ? realName.replace(".zip", "") : null);
            map.put("virtualFileName", virtualFileName);
            map.put("error", 0);
            map.put("path", filePath);
            map.put("result", true);
            map.put("message", "上传成功");
        } catch (IOException e) {
            e.printStackTrace();
            map.put("error", 1);
            map.put("message", e.getMessage());
            map.put("result", false);
        } finally {
            response.setContentType("text/html");
            // 添加头部信息,避免跨域拦截
            response.addHeader("Access-Control-Allow-Origin", "*");
            writer = response.getWriter();
            writer.println(JSON.toJSONString(map));
            writer.close();
        }
    }

    /**
     * 下载文件
     */
    @RequestMapping(value = "/download/{templateId}")
    public void download(@PathVariable() String templateId, HttpServletResponse response) throws IOException {
        // 获取路径
        Template template = templateAS.getTemplateById(templateId);
        String codePath = StringUtils.isEmpty(template.getTemplateCode()) ? "default" : template.getTemplateCode();
        String path = uploadPath + codePath + "/" + template.getVirtualFileName();
        File tempFile = new File(path);
        // 读取文件信息
        InputStream fis = new BufferedInputStream(new FileInputStream(path));
        byte[] buffer = new byte[fis.available()];
        int read = fis.read(buffer);
        System.out.println(read);
        fis.close();
        // 响应请求,文件信息放入响应的outputStream中
        response.reset();
        response.addHeader("Content-Disposition", "attachment;filename=" + tempFile.getName());
        response.addHeader("Content-Length", "" + tempFile.length());
        OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
        response.setContentType("application/octet-stream");
        toClient.write(buffer);
        toClient.flush();
        toClient.close();
    }

    /**
     * 删除文件
     */
    @RequestMapping(value = "/delFile", method = RequestMethod.POST)
    @ResponseBody
    public ResponseDto delFile(@RequestParam("filePath") String filePath) {
        ResponseDto ret = new ResponseDto();
        if (!StringUtils.isEmpty(filePath)) {
            ret.setCode(ResultCodeEnum.FAIL.getCode());
            ret.setMessage(ResultCodeEnum.PARAMETER_ERROR.getMessage());
            return ret;
        }
        File delFile = new File(filePath);
        CompressUtil.deleteFilesDir(delFile);
        ret.setCode(ResultCodeEnum.SUCCESS.getCode());
        ret.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return ret;
    }

    /**
     * 已知模板id或编码,获取文件路径
     */
    private String getPath(Template template) {
        if (template.getId() != null) {
            Template result = templateAS.getTemplateById(template.getId() + "");
            return uploadPath + result.getTemplateCode() + "/" + result.getVirtualFileName();
        }
        if (!StringUtils.isEmpty(template.getTemplateCode())) {
            Template result = templateAS.getTemplateByCode(template.getTemplateCode());
            return uploadPath + result.getTemplateCode() + "/" + result.getVirtualFileName();
        }
        return "";
    }

    /**
     * 生成编码
     */
    private String getTemplateCode() {
        Calendar calendar = Calendar.getInstance();
        String yearStr = calendar.get(Calendar.YEAR) + "";
        int month = calendar.get(Calendar.MONTH) + 1;
        String monthStr = month + "";
        if (month < 10) {
            monthStr = "0" + monthStr;
        }
        int day = calendar.get(Calendar.DATE);
        String dayStr = day + "";
        if (day < 10) {
            dayStr = "0" + dayStr;
        }
        String timeStr = yearStr + monthStr + dayStr;
        return "TE" + timeStr + SequenceTool.getSequenceNO("seq_template_code", "SYS").toString();
    }

    /**
     * 获取登陆人相关信息
     */
    private void dealUser(Template template, HttpServletRequest request, String actionType) {
        template.setOrgId(getOrgId(request));
        if ("add".equals(actionType)) {
            template.setProjectId(SessionUserCommonUtil.getSessionUser().getCurrProjectId());
            template.setCreateUser(getUserName(request));
            template.setCreateDate(new Date());
            template.setModifyUser(getUserName(request));
            template.setModifyDate(new Date());
        } else if ("update".equals(actionType)) {
            template.setModifyUser(getUserName(request));
            template.setModifyDate(new Date());
        }
    }

    private String getOrgId(HttpServletRequest request) {
        String orgId = AuthSessionFacade.getCurrOrgId(request);
        return StringUtils.isEmpty(orgId) ? "1" : orgId;
    }

    private String getUserName(HttpServletRequest request) {
        String currUserCode = AuthSessionFacade.getCurrUserCode(request);
        return StringUtils.isEmpty(currUserCode) ? "系统管理员" : currUserCode;
    }

    /**
     * 生成虚拟文件名称
     */
    private String getVirtualFileName() {
        String uid = UUID.randomUUID().toString();
        return uid.replace("-", "");
    }

}

前端vue文件,需注意下载时的代码处理:

<template>
<z-modal v-model="modelIsOpen" :title="showTitle" width="600" :mask-closable="false">
  <z-form ref="editTemplateForm" :model="formItem" :rules="ruleValidate" :label-width="120" label-position="right">
    <z-form-item label="模板名称:" prop="templateName">
      <z-input v-model="formItem.templateName" placeholder="请输入"></z-input>
    </z-form-item>
    <z-form-item label="模板编码:" prop="templateCode">
      <z-input v-model="formItem.templateCode" placeholder="请输入" disabled></z-input>
    </z-form-item>
    <z-form-item label="模板描述:" prop="templateDescribe">
      <z-input v-model="formItem.templateDescribe" type="textarea" :autosize="{minRows: 3,maxRows: 5}"
        placeholder="请输入"></z-input>
    </z-form-item>
    <z-form-item label="" v-show="editShow">
      <z-upload class="m-t-10" :action="actionUrl" :max-size="10240" name="file" :data="uploadFormItem"
            :accept="acceptType" :show-upload-list="false" :on-success="handleUploadSuccess" :on-exceeded-size="handleMaxSize" :before-upload="handleBeforeUpload">
        <z-button type="primary" ghost icon="ios-cloud-upload-outline">上传模板</z-button>
      </z-upload>
    </z-form-item>
    <z-form-item label="">
      <z-row>
        <z-col span="2">
          <img src="/static/img/zipPicture.png" width="80%" height="80%">
        </z-col>
        <z-col span="8">
          <div class="m-t-5">{{formItem.fileName}}.zip</div>
        </z-col>
        <z-col span="4" align="center">
          <z-button type="text" @click="downloadTemplate" style="color:blue">下载模板</z-button>
        </z-col>
      </z-row>
    </z-form-item>
  </z-form>
  <div slot="footer" class="ilead-modal-footer">
      <z-button v-show="editShow" :loading="loading" type="primary"
        @click="handleSave('editTemplateForm')">保存</z-button>
      <z-button @click="handleClose()">关闭</z-button>
  </div>
</z-modal>
</template>

<script>
import templateApi from '@/api/template/templateApi'
export default {
  name: 'templateEdit',
  data: function () {
    return {
      modelIsOpen: false,
      loading: false,
      editShow: true,
      showTitle: '编辑模板',
      actionUrl: '/api/template/upload',
      acceptType: '.zip',
      initVirtualFileName: '',
      formItem: {
        templateName: '',
        templateCode: '',
        templateDescribe: '',
        id: ''
      },
      uploadFormItem: {
        templateCode: ''
      },
      ruleValidate: {
        templateName: [
          {required: true, message: '模板名称为空', trigger: 'blur'}
        ]
      }
    }
  },
  methods: {
    // 保存数据(类型走更新,新增页面会走新增)
    handleSave: function (name) {
      var that = this
      var flg = 'noUpload'
      if (that.initVirtualFileName !== that.formItem.virtualFileName) {
        flg = 'upload'
      }
      // 这里我抽了个方法校验,其实可以用vue的ruleValidate校验
      var msg = that.checkForm()
      if (msg !== '') {
        that.$Message.warning({
          duration: 3,
          content: msg
        })
        return
      }
      that.loading = true
      templateApi.saveTemplate(flg, 'update', this.formItem).then(function (response) {
        console.log(response)
        that.$Message.success('保存成功')
        // 回调list页方法
        that.$emit('queryTemplate')
        that.loading = false
        that.modelIsOpen = false
      }).catch(function (error) {
        console.log(error)
        that.loading = false
        that.$Message.error('更新异常')
      })
    },
    // 校验必填字段
    checkForm: function () {
      if (this.formItem.templateName === '') {
        return '模板名称为空'
      }
      return ''
    },
    // 下载 注意Blob的处理,从响应中取出文件信息,不同类型的文件type不一样
    downloadTemplate: function (name) {
      var that = this
      templateApi.downloadTemplate(this.formItem.id).then(function (response) {
        const blob = new Blob([response.data], {type: 'application/zip; application/octet-stream'})
        const fileName = that.formItem.fileName + '.zip'
        // 点击即下载,相当a标签
        const elink = document.createElement('a')
        elink.download = fileName
        elink.style.display = 'none'
        elink.href = URL.createObjectURL(blob)
        document.body.appendChild(elink)
        elink.click()
        URL.revokeObjectURL(elink.href)
        document.body.removeChild(elink)
      }).catch(function (error) {
        console.log(error)
        that.$Message.error('下载异常')
      })
    },
    // 关闭
    handleClose: function () {
      this.handleReset()
      this.modelIsOpen = false
    },
    // 文件大小限制的提示信息
    handleMaxSize: function (file) {
      this.$Message.error('文件  ' + file.name + ' 过大.')
    },
    // 上传前执行的校验
    handleBeforeUpload: function (file) {
      if (file.name.indexOf('.zip') === -1) {
        this.$Message.warning({content: '只能上传zip文件', duration: 5})
        return false
      }
    },
    // 上传成功后的回调
    handleUploadSuccess: function (response) {
      if (response.error === 0) {
        this.$Message.success('上传成功')
        this.formItem.fileName = response.fileName
        this.formItem.virtualFileName = response.virtualFileName
      } else {
        this.$Message.warning({content: response.message, duration: 5})
      }
    },
    // 重置
    handleReset () {
      this.$refs['editTemplateForm'].resetFields()
    }
  }
}
</script>

 以上。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值