SNServiceImpl.java 6.93 KB
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<String> 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<String> 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();

    }

}