package com.example.demo.service.impl; import cn.hutool.core.codec.Base64; import com.example.demo.controller.SNController; import com.example.demo.dto.AddSNsDTO; import com.example.demo.dto.DeleteSNsDTO; import com.example.demo.exception.SNRepetitiveException; import com.example.demo.service.SNService; 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.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<>(); BufferedReader bufferedReader = new BufferedReader(new FileReader(SNFilePath)); 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()); } //写入 FileWriter fileWriter = new FileWriter(SNFilePath,true); fileWriter.write(SNs.toString()); fileWriter.flush(); fileWriter.close(); logger.info("-----------------------------结束添加SNs-----------------------------"); } finally { //释放锁 lock.unlock(); } } @Override public String getEncryptSNs() throws IOException { File file = new File(SNFilePath); //读取文件 byte[] SNsByteArr = new byte[(int) file.length()]; FileInputStream fileInputStream = new FileInputStream(file); fileInputStream.read(SNsByteArr); //加密 String encodeSNs = Base64.encode(SNsByteArr); return encodeSNs; } @Override public void deleteSN(DeleteSNsDTO deleteSNsDTO) throws Exception{ try { lock.lock(); logger.info("-----------------------------开始删除SNs-----------------------------"); HashSet deleteSNsSet = new HashSet<>(deleteSNsDTO.getSns()); //读取文件,记录不用删除的数据 BufferedReader bufferedReader = new BufferedReader(new FileReader(SNFilePath)); 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(str).append("、"); SNExist = true; } } bufferedReader.close(); //如果存在要删除的SN,先将数据备份,再将留存数据覆盖掉原SN文件,避免数据写一半断电丢失。 if (SNExist) { //备份数据 FileWriter SNTempfileWriter = new FileWriter(SNTempFilePath); SNTempfileWriter.write(stringBuilder.toString()); SNTempfileWriter.flush(); SNTempfileWriter.close(); //覆盖掉原来的数据到SN文件中 FileWriter SNfileWriter = new FileWriter(SNFilePath); SNfileWriter.write(stringBuilder.toString()); SNfileWriter.flush(); SNfileWriter.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(); } }