package com.vci.web.service.impl; import com.vci.corba.common.PLException; import com.vci.corba.volume.VolumeServicePrx; import com.vci.enumpck.VciFileTransProtocolEnum; import com.vci.pagemodel.VciFileVolumeVO; import com.vci.pagemodel.VciFileObjectVO; import com.vci.starter.web.annotation.bus.VciChangeDocument; import com.vci.starter.web.exception.VciBaseException; import com.vci.starter.web.pagemodel.BaseResult; import com.vci.starter.web.util.LocalFileUtil; import com.vci.starter.web.util.VciBaseUtil; import com.vci.starter.web.wrapper.VciQueryWrapperForDO; import com.vci.web.util.file.clientutil.VciFileServerClientUtil; import com.vci.web.dao.VciFileObjectDaoI; import com.vci.model.VciFileObjectDO; import com.vci.web.properties.WebProperties; import com.vci.web.service.VciFileDownloadServiceI; import com.vci.web.service.VciFileObjectServiceI; import com.vci.web.service.VciFileVolumeServiceI; import com.vci.web.util.PlatformClientUtil; import com.vci.web.util.file.VciZipUtil; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.io.ZipOutputStream; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.io.*; import java.util.Collection; import java.util.List; import java.util.Map; import static com.vci.constant.VciFileLangCodeConstant.FILE_NOT_FOUND; import static com.vci.constant.VciFileLangCodeConstant.FILE_READ_FAIL; import static com.vci.constant.FrameWorkLangCodeConstant.*; /** * 文件的下载服务 * @author weidy * @date 2021-3-11 */ @Service @VciChangeDocument(btmType = "fileDownload") public class VciFileDownloadServiceImpl implements VciFileDownloadServiceI { /** * 文件的对象服务 */ @Autowired private VciFileObjectServiceI vciFileObjectServiceI; /** * 文件的卷服务 */ @Autowired private VciFileVolumeServiceI vciFileVolumeServiceI; /** * 文件对象的操作 */ @Autowired private VciFileObjectDaoI vciFileObjectMapper; /** * zip操作类 */ @Autowired private VciZipUtil zipUtil; /** * 平台的客户端 */ @Autowired private PlatformClientUtil platformClientUtil; /** * 配置对象 */ @Autowired private WebProperties webProperties; /** * 根据主键下载文件,会下载到默认的临时文件夹下 * @param fileOids 文件的主键 * @return 文件在本地的全路径 * @throws VciBaseException 参数为空或者文件出错的时候会抛出异常 */ @Override public String downloadFileByOid(String fileOids) throws VciBaseException { VciBaseUtil.alertNotNull(fileOids,"文件主键"); List fileOidList = VciBaseUtil.str2List(fileOids); String tempFilePath = null; if(fileOidList.size() == 1){ String fileOid = fileOidList.get(0); VciFileObjectVO vciFileObjectVO = vciFileObjectServiceI.getObjectByOid(fileOid); VciFileVolumeVO vciFileVolumeVO = null; if(StringUtils.isNotBlank(vciFileObjectVO.getPkFileVolume())){ vciFileVolumeVO = vciFileVolumeServiceI.getObjectByOid(vciFileObjectVO.getPkFileVolume()); }else{ vciFileVolumeVO = vciFileVolumeServiceI.getObjectById(vciFileObjectVO.getFilePath().split(":")[0]); } tempFilePath = downloadFile(vciFileObjectVO,vciFileVolumeVO,LocalFileUtil.getDefaultTempFolder()); //其他的协议的后续补充 } if(fileOidList.size()>1){ tempFilePath = downloadFileByOids(fileOidList); } return tempFilePath; } /** * 执行下载 * @param vciFileObjectVO 文件的对象 * @param vciFileVolumeVO 卷的对象 * @return 下载后的地址 */ private String downloadFile(VciFileObjectVO vciFileObjectVO,VciFileVolumeVO vciFileVolumeVO,String tempFolder){ String fileName = vciFileObjectVO.getName()+"."+vciFileObjectVO.getFileExtension(); String tempDir = StringUtils.isNotBlank(tempFolder)?tempFolder:LocalFileUtil.getDefaultTempFolder(); String tempFilePath = tempDir+File.separator+vciFileObjectVO.getName()+"."+vciFileObjectVO.getFileExtension(); //本地协议 File tempFile = new File(tempFilePath); File tempDirFile = tempFile.getParentFile(); if(!tempDirFile.exists()){ tempDirFile.mkdirs(); } if(!tempFile.exists()){ try { tempFile.createNewFile(); } catch (IOException e) { throw new VciBaseException("在临时文件夹下创建临时文件出错",new String[0],e); } } if(vciFileVolumeVO.getTransProtocol().equals(VciFileTransProtocolEnum.LOCAL.getValue())){ try{ String filePath = vciFileVolumeVO.getVolumePath()+File.separator+vciFileObjectVO.getFilePath(); File file = new File(filePath); if(!file.exists()){ throw new VciBaseException(FILE_NOT_FOUND,new String[]{""}); } LocalFileUtil.copyFile(file,tempFile); }catch (Exception e){ throw new VciBaseException(DOWNLOAD_FAIL, new String[]{e.getMessage()}); } }else if(VciFileTransProtocolEnum.CORBA.getValue().equalsIgnoreCase(vciFileVolumeVO.getTransProtocol())){ String volumeName = vciFileVolumeVO.getName(); VolumeServicePrx volumnCorbaService = platformClientUtil.getVolumeService(volumeName); if(volumnCorbaService == null){ throw new VciBaseException("没有获取到卷服务"); } //平台2020版本此处修改了,卷的文件夹是由卷服务来控制 String serverPath = vciFileObjectVO.getFilePath(); long fileSize = 0; try { fileSize = volumnCorbaService.getFileSize(serverPath); } catch (PLException vciError) { throw new VciBaseException("没有在卷服务{}里获取到文件{}的大小",new String[]{volumeName,fileName},vciError); } try { FileOutputStream destFileOs = new FileOutputStream(tempFilePath); long blockSize = webProperties.getBlockLength()*1024; if(blockSize> Integer.MAX_VALUE){ blockSize = Integer.MAX_VALUE; } long temp = 0; while (fileSize - temp > blockSize) { destFileOs.write(volumnCorbaService.sendFile(serverPath, temp)); temp += blockSize; } destFileOs.write(volumnCorbaService.sendFile(serverPath, temp)); destFileOs.flush(); destFileOs.close(); } catch (FileNotFoundException e) { throw new VciBaseException("要写入的文件没有找到",new String[]{tempFilePath},e); } catch (IOException e) { throw new VciBaseException("写入文件出错" + e.getMessage(),new String[]{tempFilePath},e); } catch (PLException e){ // throw new VciBaseException("卷服务传输文件时出现了错误" + e.error_code,e.error_message,e); }catch (Exception e){ throw new VciBaseException("卷服务传输文件时出现了错误" + e.getMessage(),new String[0],e); } } return tempFilePath; } /** * 根据主键批量下载文件,会下载到默认的临时文件下 * @param fileOids 文件的主键集合 * @return 文件所在本地的压缩包的全路径 * @throws VciBaseException 参数为空或者文件出错的时候会抛出异常 */ public String downloadFileByOids(Collection fileOids) throws VciBaseException { List vciFileObjectDOS = vciFileObjectMapper.selectByPrimaryKeyCollection(fileOids); String localFolder = LocalFileUtil.getDefaultTempFolder(); String zipFileName = vciFileObjectDOS.iterator().next().getId()+"等多文件.zip"; String zipFile =localFolder + File.separator+zipFileName; File[] tempFiles = new File[vciFileObjectDOS.size()]; int i = 0; for(VciFileObjectDO vciFileObjectDO : vciFileObjectDOS){ VciFileVolumeVO vciFileVolumeVO = null; if(StringUtils.isBlank(vciFileObjectDO.getPkFileVolume()) && StringUtils.isNotBlank(vciFileObjectDO.getFilePath())){ vciFileVolumeVO = vciFileVolumeServiceI.getObjectById(vciFileObjectDO.getFilePath().split(":")[0]); }else { vciFileVolumeVO = vciFileVolumeServiceI.getObjectByOid(vciFileObjectDO.getPkFileVolume()); } String tempFilePath = downloadFile(vciFileObjectServiceI.vciFileObjectDO2VO(vciFileObjectDO),vciFileVolumeVO,localFolder); tempFiles[i] = new File(tempFilePath); i++; } zipUtil.addFileToZip(tempFiles, zipFile); //文件添加到压缩包后,将临时文件删除。 for(File file : tempFiles){ file.delete(); file.getParentFile().delete(); } return zipFile; } @Override public String downloadFileByOid(String clientPath, String fileOid) throws VciBaseException { return null; } @Override public Map batchDownloadFileByOids(Collection fileOidCollection) throws VciBaseException { return null; } @Override public Map batchDownloadFileByOids(String clientPath, Collection fileOidCollection) throws VciBaseException { return null; } @Override public Map batchDownloadFileByOids(String clientPath, Collection fileOidCollection, boolean sameFileUseOidFolder) throws VciBaseException { return null; } @Override public String downloadFileByFileObject(VciFileObjectVO fileObjectVO) throws VciBaseException { return null; } @Override public String downloadFileByFileObject(String clientPath, VciFileObjectVO fileObjectVO) throws VciBaseException { return null; } @Override public Map batchDownloadFileByFileObject(Collection fileObjectVOCollection) throws VciBaseException { return null; } @Override public Map batchDownloadFileByFileObject(String clientPath, Collection fileObjectVOCollection) throws VciBaseException { return null; } @Override public void downloadZipFileByOids(String zipFileName, String fileOid) throws VciBaseException { } @Override public void downloadZipFileByOids(ZipFile zipFile, String fileOid) throws VciBaseException { } @Override public void downloadZipStreamByOids(ZipOutputStream zipOutputStream, String fileOid) throws VciBaseException { } @Override public void downloadZipFileByOids(String zipFileName, Collection fileOidCollection) throws VciBaseException { } @Override public void downloadZipFileByOids(ZipFile zipFile, Collection fileOidCollection) throws VciBaseException { } @Override public void downloadZipStreamByOids(ZipOutputStream zipOutputStream, Collection fileOidCollection) throws VciBaseException { } @Override public void downloadZipFileByOids(ZipFile zipFile, Collection fileOidCollection, boolean sameFileUseOidFolder) throws VciBaseException { } @Override public void downloadZipStreamByOids(ZipOutputStream zipOutputStream, Collection fileOidCollection, boolean sameFileUseOidFolder) throws VciBaseException { } /** * 分片下载 * @param fileOid 文件主键 * @param offSet 偏移量 * @return 数据 * @throws VciBaseException 下载出错的时候会抛出异常 */ @Override public BaseResult sectionDownloadByFileOid(String fileOid, long offSet) throws VciBaseException { BaseResult baseResult = new BaseResult(); VciFileObjectVO vciFileObjectVO = vciFileObjectServiceI.getObjectByOid(fileOid); VciFileVolumeVO vciFileVolumeVO = null; if(StringUtils.isBlank(vciFileObjectVO.getPkFileVolume()) && StringUtils.isNotBlank(vciFileObjectVO.getFilePath())){ vciFileVolumeVO = vciFileVolumeServiceI.getObjectById(vciFileObjectVO.getFilePath().split(":")[0]); }else { vciFileVolumeVO = vciFileVolumeServiceI.getObjectByOid(vciFileObjectVO.getPkFileVolume()); } String fileName = vciFileObjectVO.getName()+"."+vciFileObjectVO.getFileExtension(); //本地协议 if(vciFileVolumeVO.getTransProtocol().equals(VciFileTransProtocolEnum.LOCAL.getValue())){ String sourceFilePath = vciFileVolumeVO.getVolumePath()+File.separator+vciFileObjectVO.getFilePath(); File sourceFile = new File(sourceFilePath); if(!sourceFile.exists()){ throw new VciBaseException(FILE_NOT_FOUND,new String[]{""}); } long fileSize = sourceFile.length(); RandomAccessFile destfile = null; try{ byte[] buffer ; if(offSet<(fileSize- VciFileServerClientUtil.BLOCKSIZE)){ buffer = new byte[VciFileServerClientUtil.BLOCKSIZE]; }else{ buffer = new byte[(int) (fileSize-offSet)]; } destfile = new RandomAccessFile(sourceFile, "rw"); destfile.seek(offSet); destfile.read(buffer); baseResult.setSuccess(true); baseResult.setMsg(DOWNLOAD_SUCCESS); baseResult.setObj(buffer); } catch (Exception e){ throw new VciBaseException(FILE_READ_FAIL,new String[]{vciFileObjectVO.getName()}); }finally { if(destfile != null){ try { destfile.close(); } catch (IOException e) { e.printStackTrace(); } } } }else if(VciFileTransProtocolEnum.CORBA.getValue().equalsIgnoreCase(vciFileVolumeVO.getTransProtocol())){ String volumeName = vciFileVolumeVO.getName(); VolumeServicePrx volumnCorbaService = platformClientUtil.getVolumeService(volumeName); if(volumnCorbaService == null){ throw new VciBaseException("没有获取到卷服务"); } String serverPath = vciFileVolumeVO.getVolumePath() + File.separator + vciFileObjectVO.getFilePath().replace(volumeName+":",""); long fileSize = 0; try { fileSize = volumnCorbaService.getFileSize(serverPath); } catch (PLException vciError) { throw new VciBaseException("没有在卷服务{}里获取到文件{}的大小",new String[]{volumeName,fileName},vciError); } try { baseResult.setSuccess(true); baseResult.setMsg(DOWNLOAD_SUCCESS); baseResult.setObj( volumnCorbaService.sendFile(serverPath, fileSize-offSet)); } catch (Exception e){ throw new VciBaseException(FILE_READ_FAIL,new String[]{vciFileObjectVO.getName()}); } } //其他协议的下载,后续完善 return baseResult; } /** * 删除文件 * @param fileOidCollection 文件主键集合 * @return 执行结果 * @throws VciBaseException 删除出错的时候会抛出异常 */ @Override public BaseResult deleteFile(Collection fileOidCollection) throws VciBaseException { List fileObjectDOList = vciFileObjectMapper.selectByPrimaryKeyCollection(fileOidCollection); for(VciFileObjectDO fileObjectDO : fileObjectDOList){ VciFileVolumeVO fileVolumeVO = vciFileVolumeServiceI.getObjectByOid(fileObjectDO.getPkFileVolume()); //本地协议 if(fileVolumeVO.getTransProtocol().equals(VciFileTransProtocolEnum.LOCAL.getValue())){ String volumePath = fileVolumeVO.getVolumePath(); String filePath = volumePath+File.separator+fileObjectDO.getFilePath(); File file = new File(filePath); if(file.exists()){ file.delete(); } File dirFile = file.getParentFile(); if(dirFile.listFiles().length>0){ //说明此目录下还有其他文件,此目录不能删除 }else{ dirFile.delete(); } vciFileObjectMapper.deleteByPrimaryKey(fileObjectDO.getOid()); }else if(VciFileTransProtocolEnum.CORBA.getValue().equalsIgnoreCase(fileVolumeVO.getTransProtocol())){ //暂时不删除文件 vciFileObjectMapper.deleteByPrimaryKey(fileObjectDO.getOid()); } //其他协议,后续完善 } return BaseResult.success(DELETE_SUCCESS); } /** * 使用卷服务上的文件路径来下载 * * @param filePath 文件的路径 * @return 下载后的地址 * @throws VciBaseException 下载出错会抛出异常 */ @Override public String downloadFileByPath( String filePath) throws VciBaseException { VciBaseUtil.alertNotNull(filePath,"文件路径"); String volumeId = ""; if (filePath.contains(":")) { volumeId = filePath.split(":")[0]; filePath = filePath.split(":")[1]; } else { throw new VciBaseException("文件的路径格式不正确,需要xxx:yyyy"); } VciFileVolumeVO vciFileVolumeVO = vciFileVolumeServiceI.getObjectById(volumeId); if(filePath.contains(".")){ //直接传递的完整的路径 String tempFilePath = LocalFileUtil.getDefaultTempFolder() + File.separator ; String fileName = ""; if(filePath.contains(File.separator)){ fileName = filePath.substring(filePath.lastIndexOf(File.separator)+1); }else{ if(filePath.contains("/")){ fileName= filePath.substring(filePath.lastIndexOf("/")+1); }else{ fileName = filePath.replace(volumeId+":",""); } } tempFilePath = tempFilePath+fileName; File tempFile = new File(tempFilePath); File tempDirFile = tempFile.getParentFile(); if(!tempDirFile.exists()){ tempDirFile.mkdirs(); } if(!tempFile.exists()){ try { tempFile.createNewFile(); } catch (IOException e) { throw new VciBaseException("在临时文件夹中创建临时文件出错",new String[0],e); } } if(vciFileVolumeVO.getTransProtocol().equals(VciFileTransProtocolEnum.LOCAL.getValue())){ try{ File file = new File(filePath.replace(volumeId + ":",vciFileVolumeVO.getVolumePath())); if(!file.exists()){ throw new VciBaseException(FILE_NOT_FOUND,new String[]{""}); } LocalFileUtil.copyFile(file,tempFile); }catch (Exception e){ throw new VciBaseException(DOWNLOAD_FAIL, new String[]{e.getMessage()}); } }else if(VciFileTransProtocolEnum.CORBA.getValue().equalsIgnoreCase(vciFileVolumeVO.getTransProtocol())){ String volumeName = vciFileVolumeVO.getName(); VolumeServicePrx volumnCorbaService = platformClientUtil.getVolumeService(volumeName); if(volumnCorbaService == null){ throw new VciBaseException("没有获取到卷服务"); } //平台2020版本此处修改了,卷的文件夹是由卷服务来控制 String serverPath = volumeId+":" + filePath; long fileSize = 0; try { fileSize = volumnCorbaService.getFileSize(serverPath); } catch (PLException vciError) { throw new VciBaseException("没有在卷服务{}里获取到文件{}的大小",new String[]{volumeName,fileName},vciError); } try { FileOutputStream destFileOs = new FileOutputStream(tempFilePath); long blockSize = webProperties.getBlockLength()*1024; if(blockSize> Integer.MAX_VALUE){ blockSize = Integer.MAX_VALUE; } long temp = 0; while (fileSize - temp > blockSize) { destFileOs.write(volumnCorbaService.sendFile(serverPath, temp)); temp += blockSize; } destFileOs.write(volumnCorbaService.sendFile(serverPath, temp)); destFileOs.flush(); destFileOs.close(); } catch (FileNotFoundException e) { throw new VciBaseException("要写入的文件没有找到",new String[]{tempFilePath},e); } catch (IOException e) { throw new VciBaseException("写入文件出错" + e.getMessage(),new String[]{tempFilePath},e); } catch (PLException e){ // throw new VciBaseException("卷服务传输文件时出现了错误" + e.error_code,e.error_message,e); }catch (Exception e){ throw new VciBaseException("卷服务传输文件时出现了错误" + e.getMessage(),new String[0],e); } } return tempFilePath; }else { VciQueryWrapperForDO queryWrapperForDO = new VciQueryWrapperForDO(null, VciFileObjectDO.class); queryWrapperForDO.eq("filepath", volumeId + ":" + filePath); List fileObjectDOS = vciFileObjectMapper.selectByWrapper(queryWrapperForDO); if (CollectionUtils.isEmpty(fileObjectDOS)) { throw new VciBaseException("没有找到这个路径下的文件信息"); } return downloadFile(vciFileObjectServiceI.vciFileObjectDO2VO(fileObjectDOS.get(0)), vciFileVolumeVO,null); } } }