zip导入
public SwaggerResultUtil<String> importDefinition(@RequestParam(value = "file") MultipartFile file) {
SwaggerResultUtil<String> resultUtil;
String fileName = file.getOriginalFilename();
ZipInputStream zs = null;
BufferedInputStream bs = null;
try {
String extension = FilenameUtils.getExtension(fileName);
if (extension.equals("zip")) {
zs = new ZipInputStream(file.getInputStream(), Charset.forName("GBK"));// 中文文件名
bs = new BufferedInputStream(zs);
List<ProcessDefinitionEntity> entities = new ArrayList<>();
ZipEntry ze;
while ((ze = zs.getNextEntry()) != null) { // 获取zip包中的每一个zip file entry
long size = ze.getSize();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = null;
if (size == -1) { // 当你的文件是程序导出,且没指定长度时可能发生这类情况,长度为-1,但是有内容。
while (true) {
int zsize = zs.read();
if (zsize == -1) {
break;
}
baos.write(zsize);
}
} else {
bytes = new byte[(int) size];
bs.read(bytes, 0, (int) ze.getSize());
}
}
resultUtil = definitionService.insertSelectiveBatch(entities);
} else {
resultUtil = SwaggerResultUtil.resultError(ErrorCodeEnum.INCORRECT_FILE_FORMAT.getCode(), ErrorCodeEnum.INCORRECT_FILE_FORMAT.getMsg());
}
} catch (Exception e) {
logger.error("转换流时发生异常!", e);
resultUtil = SwaggerResultUtil.error500("文件内容格式有误!");
} finally {
try {
bs.close();
zs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultUtil;
}
有几个注意点已经加了注释
1.当zip包里面的文件有中文名时, zs = new ZipInputStream(file.getInputStream(), Charset.forName(“GBK”));此行代码请指定编码为gbk。
2.当long size = ze.getSize();zip包里面的entry有流数据但是长度为-1时,特殊处理,直接读取到流结束,一般出现这种情况的原因是用程序导出,且没有指定长度(看下面的导出方法)时造成的,当你操作一下这个文件后会自动加上长度,比如给改文件名等。
zip导出
public void exportDefinition(
@ApiParam(name = "definitionIds",value = "流程定义id【多个用英文,分隔】",required = true) @RequestParam String definitionIds, HttpServletResponse response) {
if (StringUtils.isNotEmpty(definitionIds)) {
String[] ids = definitionIds.split(",");
List<ProcessDefinitionEntityWithBLOBs> blobs = definitionService.getDefinitionListByIds(Arrays.asList(ids));
if (CollectionUtils.isNotEmpty(blobs)) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (ZipOutputStream zip = new ZipOutputStream(outputStream)) {
for (ProcessDefinitionEntityWithBLOBs bs : blobs) {
CommonUtil.createZip(bs.getName(), bs.getJsonBytes(), zip);
}
} catch (Exception e) {
e.printStackTrace();
}
try {
IOUtils.write(outputStream.toByteArray(), response.getOutputStream());
response.setHeader("Content-Disposition", "attachment; filename=flow.zip");
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @param entryName zip中的文件名
* @param srcByte 二进制数据
* @param zip zip输出流
*/
public static void createZip(String entryName, byte[] srcByte, ZipOutputStream zip) {
try {
zip.putNextEntry(new ZipEntry(entryName + ".flow"));
IOUtils.write(srcByte, zip);
zip.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
}
导出时未指定长度就会发生上面导入时提到的问题。
class ZipEntry implements ZipConstants, Cloneable {
String name; // entry name
long xdostime = -1; // last modification time (in extended DOS time,
// where milliseconds lost in conversion might
// be encoded into the upper half)
FileTime mtime; // last modification time, from extra field data
FileTime atime; // last access time, from extra field data
FileTime ctime; // creation time, from extra field data
long crc = -1; // crc-32 of entry data
long size = -1; // uncompressed size of entry data
long csize = -1; // compressed size of entry data
int method = -1; // compression method
int flag = 0; // general purpose flag
byte[] extra; // optional extra field data for entry
String comment; // optional comment string for entry
注意:导入导出结束关闭流且要顺序正确,先打开的后关闭,不然解压时会报“不可预料的压缩文件末端”。
版权声明:本文为zpfzly原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。