package com.ectrip.demo.service.impl; import cn.hutool.core.codec.Base64; import com.ectrip.demo.dto.DeleteSNsDTO; import com.ectrip.demo.service.SNService; import com.ectrip.demo.dto.AddSNsDTO; import com.ectrip.demo.exception.SNRepetitiveException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @Service public class SNServiceImpl implements SNService { /** * 多线程改写文件存在并发问题,需加锁操作 */ private static final Lock lock = new ReentrantLock(); static Logger logger = LogManager.getLogger(SNServiceImpl.class); @Value("${SN.file.path}") String SNFilePath; @Value("${SN.file.temp.path}") String SNTempFilePath; @Override public void addSN(AddSNsDTO addSNsDTO) throws SNRepetitiveException, IOException { //加try,catch只为释放锁 try { //加锁 lock.lock(); logger.info("-----------------------------开始添加SNs-----------------------------"); StringBuilder SNs = new StringBuilder(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String currTime = sdf.format(new Date()); //读取文件,判断SN是否重复 Set set = new HashSet<>(); Reader reader = new InputStreamReader(Files.newInputStream(Paths.get(SNFilePath)),StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(reader); String br; while ((br=bufferedReader.readLine()) != null) { //截取SN int index = br.indexOf("##"); String SN = br.substring(0,index == -1? 0 : index); set.add(SN); } for (String SN : addSNsDTO.getSns()) { if (set.contains(SN)) { throw new SNRepetitiveException("SN:" + SN + " 已存在,请勿重复添加"); } SNs.append(SN).append("##").append(addSNsDTO.getProjectName()).append("##").append(currTime); SNs.append(System.lineSeparator()); } //写入 FileOutputStream fileOutputStream = new FileOutputStream(SNFilePath,true); fileOutputStream.write(SNs.toString().getBytes(StandardCharsets.UTF_8)); fileOutputStream.flush(); fileOutputStream.close(); logger.info("成功写入SNs:{}",SNs); } finally { //释放锁 lock.unlock(); } } @Override public String getEncryptSNs() throws IOException { //读取文件 Reader reader = new InputStreamReader(Files.newInputStream(Paths.get(SNFilePath)),StandardCharsets.UTF_8); char[] chars = new char[1000]; StringBuilder builder = new StringBuilder(); int len = reader.read(chars); while (len != -1) { builder.append(chars,0,len); len = reader.read(chars); } //加密 return Base64.encode(builder.toString()); } @Override public void deleteSN(DeleteSNsDTO deleteSNsDTO) throws Exception{ try { lock.lock(); logger.info("-----------------------------开始删除SNs-----------------------------"); HashSet deleteSNsSet = new HashSet<>(deleteSNsDTO.getSns()); //读取文件,记录不用删除的数据 Reader reader = new InputStreamReader(Files.newInputStream(new File(SNFilePath).toPath()), StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(reader); String br; StringBuilder stringBuilder = new StringBuilder(); StringBuilder existSNs = new StringBuilder(); //所要删除的SN是否存在 boolean SNExist = false; while ((br=bufferedReader.readLine()) != null) { //截取SN int index = br.indexOf("##"); String str = br.substring(0,index == -1? 0 : index); if (!deleteSNsSet.contains(str)) { stringBuilder.append(br); stringBuilder.append(System.lineSeparator()); } else { existSNs.append(br).append(System.lineSeparator()); SNExist = true; } } bufferedReader.close(); //如果存在要删除的SN,先将数据备份,再将留存数据覆盖掉原SN文件。 if (SNExist) { //备份数据 FileOutputStream tempFileOutputStream = new FileOutputStream(SNTempFilePath); tempFileOutputStream.write(stringBuilder.toString().getBytes(StandardCharsets.UTF_8)); tempFileOutputStream.flush(); tempFileOutputStream.close(); //覆盖掉原来的数据到SN文件中 FileOutputStream fileOutputStream = new FileOutputStream(SNFilePath); fileOutputStream.write(stringBuilder.toString().getBytes(StandardCharsets.UTF_8)); fileOutputStream.flush(); fileOutputStream.close(); logger.warn("成功删除SNs:{}",existSNs); } logger.info("-----------------------------结束删除SNs-----------------------------"); } finally { lock.unlock(); } } @Override public void downloadSNFile(HttpServletRequest request, HttpServletResponse response) throws IOException { File file = new File(SNFilePath); response.setCharacterEncoding("UTF-8"); response.setHeader("Content-type","application/octet-stream;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(file.getName().trim(), "UTF-8")); response.addHeader("Pargam", "no-cache"); response.addHeader("Cache-Control", "no-cache"); //读取文件 byte[] SNsByteArr = new byte[(int) file.length()]; FileInputStream fileInputStream = new FileInputStream(file); fileInputStream.read(SNsByteArr); //加密 String encodeSNs = Base64.encode(SNsByteArr); //写入到输出流 response.addHeader("Content-Length",String.valueOf(encodeSNs.getBytes().length)); OutputStream outputStream = response.getOutputStream(); outputStream.write(encodeSNs.getBytes()); outputStream.flush(); outputStream.close(); } }