WebService传递文件夹实战---服务端

我要传的是一个每天9-11点生成的500M的文件夹,WebService服务是以接口形式传输数据,无法直接传递文件,我将其压缩为zip格式,然后转换为字符串,以对象形式传递,在客户端解析解压整合成原来的文件,从而实现文件夹的传输。
文件结构如下
WebService传递文件夹实战---服务端_第1张图片

1.准备工作

pom



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.3.RELEASE
         
    
    com.gwhn
    webservice
    0.0.1-SNAPSHOT
    webservice
    war
    Demo project for Spring Boot

    
        1.8
        UTF-8
        UTF-8
    

    
        
            org.springframework.boot
            spring-boot-starter-web-services
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
        
            org.springframework.boot
            spring-boot-starter-web
            
            
                
                    org.springframework.boot
                    spring-boot-starter-tomcat
                
            
        
        
            javax.servlet
            javax.servlet-api
            4.0.1
            provided
        
        
        
            org.apache.cxf
            cxf-rt-frontend-jaxws
            3.2.6
        
        
            org.apache.cxf
            cxf-rt-transports-http
            3.2.6
        

        
            junit
            junit
            4.12
        
        
            commons-io
            commons-io
            2.5
        
        
        
            org.junit.jupiter
            junit-jupiter-api
            5.1.0-M2
            test
        
        
        
        
            org.apache.axis2
            axis2
            1.7.9
            pom
        
        
        
            net.iharder
            base64
            2.3.9
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



//建立对象
public class MicapsData implements Serializable{

    private static final long serialVersionUID = -2506579878568411053L;
    private String fileName;//micaps文件名
    private String encodedFileString;//每次传输的字符串
}
//日期工具
public class DateUtil {
    /**
     * 获取当前时间数字
     */
    public String getDate() {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd HH:mm:ss");//20190822 12:50:02
        String day = simpleDateFormat.format(date);
        return day.toString();
    }

/**
     * 获取前推,后推日期日期yyyyMMdd
     * */
    public String getDate(int num){
        Date date = new Date();//获取当前时间
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE,num);//日期往前推一天
        date = calendar.getTime();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyMMdd");
        return simpleDateFormat.format(date).toString();
    }
}
//路径配置文件
pathconfig.txt
每日micaps文件夹路径:D:\\zhpfile\\ideaworkspace
临时文件夹路径:D:\\zhpfile\\ideaworkspace\\gz
日志存放路径:D:\\zhpfile\\ideaworkspace\\gwhnWebServiceLog
其他新增配置请联系xxxx

路径配置文件在resources文件夹下,我写了一个类专门读取这些路径

public class ReadConfig {

    /**
     * 读取配置文件所有字符
     * */
    public String readConfig() throws IOException,Exception{
        BufferedReader bufferedReader = null;
        URL url = ReadConfig.class.getClassLoader().getResource("pathconfig.txt");//文件路径
        File file = new File(url.getFile());
        FileReader fileReader = new FileReader(url.getFile());//得到配置文件
        bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file.getPath()), "utf-8"));  ;//用字符流读取
        String word = "";
        String str="";
        while((str=bufferedReader.readLine())!=null)    {    //●判断最后一行不存在,为空
            word = word + str;
        }
        bufferedReader.close();//关闭字符流
        fileReader.close();
        return word;
    }

    /**
     * 从pathconfig中提取每日micaps文件夹上一级路径
     * */
    public String getMicapPath() throws Exception{
        String configPath = readConfig().substring(readConfig().indexOf("每日micaps文件夹路径:")+14,readConfig().indexOf("临时文件夹路径:"));
        DateUtil dateUtil = new DateUtil();
        return configPath+"\\"+dateUtil.getDate(-1);//业务化运行使用的路径
//        return "D:\\zhpfile\\ideaworkspace\\19102820";
    }

    /**
     * 从pathconfig中提取每日临时文件夹路径
     * */
    public String getTempPath() throws Exception{
        return readConfig().substring(readConfig().indexOf("临时文件夹路径:")+8,readConfig().indexOf("日志存放路径:"));//业务化运行使用的路径
//        return "D:\\zhpfile\\ideaworkspace\\gz";
    }

    public String getLogPath() throws Exception{
        return readConfig().substring(readConfig().indexOf("日志存放路径:")+7,readConfig().indexOf("其他新增配置"));//业务化运行使用的路径
    }
    
}

2.文件处理

public interface ZipFileService {
    public void FileToZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws RuntimeException;
    public void ZipToFile(File srcFile, String destDirPath);
    public void compress(File sourceFile, ZipOutputStream zos, String name,
                         boolean KeepDirStructure) throws Exception;
    public void copyFile(File fromFile,File toFile) throws Exception;
    public String[] getFileList(File file) ;
    public void deleteDirectory(File file);
}
public class ZipFileServiceImpl implements ZipFileService {
    private static final int BUFFER_SIZE = 2 * 1024;

    /**
     * 原始压缩成ZIP 方法
     * 由于文件太大无法传输,所以我修改成先压为为几个包,而后分开传输,到客户端解压到同一文件夹下
     * @param srcDir           压缩文件夹路径
     * @param out              压缩文件输出流
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
     *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public void FileToZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws RuntimeException {
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            File sourceFile = new File(srcDir);
            compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
            long end = System.currentTimeMillis();
            System.out.println(srcDir+"压缩完成,耗时:" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * zip解压
     * @param srcFile        zip源文件
     * @param destDirPath     解压后的目标文件夹
     * @throws RuntimeException 解压失败会抛出运行时异常
     */
    @Override
    public void ZipToFile(File srcFile, String destDirPath) {
        long start = System.currentTimeMillis();
        if (!srcFile.exists()) { // 判断源文件是否存在
            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
        }
        // 开始解压
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile);
            Enumeration entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                System.out.println("解压" + entry.getName());
                if (entry.isDirectory()) { // 如果是文件夹,就创建个文件夹
                    String dirPath = destDirPath + "/" + entry.getName();
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    File targetFile = new File(destDirPath + "/" + entry.getName());// 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                    if(!targetFile.getParentFile().exists()){ // 保证这个文件的父文件夹必须要存在
                        targetFile.getParentFile().mkdirs();
                    }
                    targetFile.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    InputStream is = zipFile.getInputStream(entry);
                    FileOutputStream fos = new FileOutputStream(targetFile);
                    int len;
                    byte[] buf = new byte[BUFFER_SIZE];
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    fos.close();// 关流顺序,先打开的后关闭
                    is.close();
                }
            }
            long end = System.currentTimeMillis();
            System.out.println("解压完成,耗时:" + (end - start) +" ms");
        } catch (Exception e) {
            throw new RuntimeException("unzip error from ZipUtils", e);
        } finally {
            if(zipFile != null){
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 递归压缩方法
     * @param sourceFile       源文件
     * @param zos              zip输出流
     * @param name             压缩后的名称
     * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
     *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws Exception
     */
    public void compress(File sourceFile, ZipOutputStream zos, String name,
                         boolean KeepDirStructure) throws Exception {
        byte[] buf = new byte[BUFFER_SIZE];
        if (sourceFile.isFile()) {
            // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
            // copy文件到zip输出流中
            int len;
            FileInputStream in = new FileInputStream(sourceFile);
            while ((len = in.read(buf)) != -1) {
                zos.write(buf, 0, len);
            }
            // Complete the entry
            zos.closeEntry();
            in.close();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
                if (KeepDirStructure) {
                    // 空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name + "/"));
                    // 没有文件,不需要文件的copy
                    zos.closeEntry();
                }
            } else {
                for (File file : listFiles) {
                    // 判断是否需要保留原来的文件结构
                    if (KeepDirStructure) {
                        // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
                        // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
                        compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
                    } else {
                        compress(file, zos, file.getName(), KeepDirStructure);
                    }
                }

            }
        }
    }

    /**
     * 复制文件
     * @param fromFile
     * @param toFile
     * 
* 2016年12月19日 下午3:31:50 * @throws IOException */ @Override public void copyFile(File fromFile, File toFile) throws Exception { FileInputStream ins = new FileInputStream(fromFile); FileOutputStream out = new FileOutputStream(toFile); byte[] b = new byte[1024]; int n=0; while((n=ins.read(b))!=-1){ out.write(b, 0, n); } ins.close(); out.close(); } /** * 获取一个文件夹下所有文件名 * */ @Override public String[] getFileList(File file) { return new String[0]; } // 删除文件夹 @Override public void deleteDirectory(File file) { if (file.isFile()) {// 表示该文件不是文件夹 file.delete(); } else { String[] childFilePaths = file.list();// 首先得到当前的路径 for (String childFilePath : childFilePaths) { File childFile = new File(file.getAbsolutePath() + "/" + childFilePath); deleteDirectory(childFile); } file.delete(); } } }

3.要暴露服务的接口,重点来了
注意文件转字符串的类在net.iharder下,
接口路径如下
@WebService(targetNamespace = “http://service.gwhn.com/”, endpointInterface = “com.gwhn.service.FileService”)
前面是服务空间,倒序到服务为止,后面是正序接口类,写到要使用的接口

@WebService
public interface FileService {

    @WebMethod
    public MicapsData getZipMicapsdata(String name,String date) throws Exception;

    @WebMethod
    public int deleteTempFiles(int sendOver)throws Exception;
}


import com.gwhn.dao.FileDao;
import com.gwhn.dao.impl.FileDaoImpl;
import com.gwhn.entity.MicapsData;
import com.gwhn.service.FileService;
import com.gwhn.service.ZipFileService;
import com.gwhn.util.DateUtil;
import com.gwhn.util.LogUtil;
import com.gwhn.util.ReadConfig;
import net.iharder.*;
import net.iharder.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.jws.WebService;
import java.io.*;
import java.util.*;

/**
 * Created by DLuser on 2019/10/30.
 */
@WebService(targetNamespace = "http://service.gwhn.com/", endpointInterface = "com.gwhn.service.FileService")
@Component
public class FileServiceImpl implements FileService {
    ReadConfig readConfig = new ReadConfig();
    private Map micapsDataMap = new HashMap();
    String filename = "";

    public FileServiceImpl() throws Exception {

    }

    /**
     * 根据文件名获取当天预测文件形成的字符串
     */
    @Override
    public MicapsData getZipMicapsdata(String name, String date) throws Exception {
        ZipFileService zipFileService = new ZipFileServiceImpl();
        DateUtil dateUtil = new DateUtil();
        try{
            if (name.equals("1") && date.equals("1")) {
                zipFileService.deleteDirectory(new File(readConfig.getTempPath()));
                LogUtil logUtil = new LogUtil();
                System.out.println("本次传输完毕");
                logUtil.writeLog(dateUtil.getDate()+name+"传输成功");
                return null;//传来传输完毕信号,处理缓存
            } else {
                String tempPath = readConfig.getTempPath();//获取临时文件夹路径D:\zhpfile\ideaworkspace\gz
                System.out.println("临时文件夹路径:" + tempPath);
                String micapsPath = readConfig.getMicapPath();//获取micaps文件夹路径D:\zhpfile\ideaworkspace\19102820
                System.out.println("micaps文件夹路径:" + micapsPath);
                String dateString = dateUtil.getDate(-1);//19082220
                File file = new File(tempPath);
                if (!file.exists()) {
                    file.mkdirs();
                }
//        File file1 = new File(tempPath + "\\" + date + "log.txt");
                System.out.println("对方传递的当天日期字符串:" + date);
                if (date.equals(dateString)) {
                    file.mkdirs();
                    if (name.equals(dateString + "10FG6.zip")) {
                        System.out.println("开始复制"+micapsPath+"中零散数据到"+tempPath);
                        copyFiles(micapsPath, tempPath, dateString);//复制四中数据到指定目录下
                        zipFiles(micapsPath, tempPath, dateString); /**分别压缩四个文件*/
                    }

                    /**将当天的各项micaps数据存入映射*/
                    List filesList = getFilNameStringList();
                    for (int i = 0; i < filesList.size(); i++) {
                        file = new File(tempPath + "\\" + dateString + filesList.get(i) + ".zip");
                        MicapsData micapsData = new MicapsData();
                        micapsData.setFileName(file.getName());
                        FileDao fileDao = new FileDaoImpl();
                        String fileString = fileDao.getFileByteString(file);
                        micapsData.setEncodedFileString(fileDao.getFileByteString(file));
                        micapsDataMap.put(file.getName(), micapsData);
                    }
                }
                filename = name;
                System.out.println("对方请求的的文件名:" + filename);
                MicapsData micapsData = micapsDataMap.get(filename);
                return micapsData;
            }
        }catch (Exception e){
            DateUtil dateUtil1 = new DateUtil();
            LogUtil logUtil = new LogUtil();
            logUtil.writeLog(dateUtil.getDate()+"传输失败");
            System.out.println("传输失败");
        }
        return null;
    }

    /**
     * 接收到对方传来的传输完毕信息,删除缓存文件夹
     */
    @Override
    public int deleteTempFiles(int sendOver) throws Exception {
        if (sendOver == 1) {
            ZipFileService zipFileService = new ZipFileServiceImpl();
            File file = new File(readConfig.getTempPath());
            zipFileService.deleteDirectory(file);
        }
        return 1;
    }


    /**
     * 复制当天对应的文件
     */
    public void copyFiles(String micapsPath, String tempPath, String dateString) throws Exception {
        ZipFileService zipFileService = new ZipFileServiceImpl();
        File file = new File(micapsPath);
        List micapsFileList = new ArrayList();
        File[] fileList = file.listFiles();
        for (int i = 0; i < fileList.length; i++) {
            if (!fileList[i].isDirectory()) {
                File srcfile = new File(fileList[i].getPath());
//                    File gzFile = new File("D:\\zhpfile\\ideaworkspace\\gz19102820\\");
                File gzFile = new File(tempPath + "\\" + dateString + "gz");
                if (!gzFile.exists()) {
                    gzFile.mkdirs();
                }
                File tofile = new File(gzFile.getPath() + "\\" + srcfile.getName());
                zipFileService.copyFile(srcfile, tofile);

            }
        }
        FileOutputStream out = new FileOutputStream(new File(tempPath + "\\" + dateString + "gz.zip"));
        zipFileService.FileToZip(tempPath + "\\" + dateString + "gz", out, true);
    }

    /**
     * 生成文件夹字符集合
     */
    public List getFilNameStringList() {
        List pathList = new ArrayList();
        pathList.add("10FG6");
        pathList.add("WIND_10M");
        pathList.add("WIND10M");
        pathList.add("gz");
        return pathList;
    }

    /**
     * 压缩四个文件夹到指定目录下
     */
    public void zipFiles(String micapsPath, String tempPath, String dateString) throws Exception {
        ZipFileService zipFileService = new ZipFileServiceImpl();
        OutputStream outputStream = new FileOutputStream(tempPath + "\\" + dateString + "10FG6.zip");
        zipFileService.FileToZip(micapsPath + "\\10FG6", outputStream, true);
        outputStream = new FileOutputStream(tempPath + "\\" + dateString + "WIND_10M.zip");
        zipFileService.FileToZip(micapsPath + "\\WIND_10M", outputStream, true);
        outputStream = new FileOutputStream(tempPath + "\\" + dateString + "WIND10M.zip");
        zipFileService.FileToZip(micapsPath + "\\WIND10M", outputStream, true);
    }

}

将文件转换为字符串!!!

@Component
public class FileDaoImpl implements FileDao {
    /**
     * 将文件转换为字符串
     */
    @Override
    public String getFileByteString(File file) throws Exception {
        String encodedFileString = "";
        InputStream inputStream = new FileInputStream(file);
        long length = file.length();// 取得文件大小
        byte[] bytes = new byte[(int) length];// 根据大小创建字节数组,每次大约20M
        int offset = 0;// 读取文件内容到字节数组
        int numRead = 0;
        while (offset < bytes.length
                && (numRead = inputStream.read(bytes, offset, bytes.length - offset)) >= 0) {
            offset += numRead;
        }
        if (offset < bytes.length) {// 读取完毕的校验
            throw new IOException("不能完全讀取文件:" + file.getName());
        }
        inputStream.close();
        encodedFileString = Base64.encodeBytes(bytes);
        return encodedFileString;
    }
}

5,webservice服务配置,这是关键

import com.gwhn.service.FileService;
import com.gwhn.service.impl.FileServiceImpl;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.xml.ws.Endpoint;

/**
 * Created by DLuser on 2019/10/28.
 */
@Configuration
public class WebServiceConfig {

    @Bean
    public ServletRegistrationBean dispatcherServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/service/*");//发布服务名称
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }

    @Bean
    public FileService fileService() throws Exception{
        return new FileServiceImpl();
    }

    @Bean
    public Endpoint endpoint() throws Exception{
        EndpointImpl endpoint = new EndpointImpl(springBus(), fileService());//绑定要发布的服务
        endpoint.publish("/micapsdata"); //显示要发布的名称
        return endpoint;
    }
}

然后是日志书写,这个需求是有时间和是否成功,我写的很简单

public class LogUtil {

    /**
     * 获取日志文件
     */
    public File getLogFile() throws Exception {
        ReadConfig readConfig = new ReadConfig();
        File file = new File(readConfig.getLogPath()+".txt");
        if (!file.exists()) {
            file.createNewFile();
        }
        return file;
    }

    /**
     * 获取日志文件所有字符,本方法建议不要和readConfig中的合并
     */
    public String getLogString() throws Exception {
        File file = getLogFile();
        BufferedReader bufferedReader = null;
        FileReader fileReader = new FileReader(file);//得到配置文件
        bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file.getPath()), "utf-8"));
        ;//用字符流读取
        String word = "";
        String str = "";
        while ((str = bufferedReader.readLine()) != null) {    //●判断最后一行不存在,为空
            word = word + str;
        }
        bufferedReader.close();//关闭字符流
        fileReader.close();
        return word;
    }

    /**
     * 获取日志文件'所有字符
     */
    public void writeLog(String content) throws Exception {
        FileOutputStream fileOutputStream = null;
        ReadConfig readConfig = new ReadConfig();
        File file = getLogFile();
        String oldContent = getLogString();
        fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write((oldContent+"\t\t"+content).getBytes());
        fileOutputStream.flush();
        fileOutputStream.close();
    }
}

最后是启动类,是已经可以打包扔到tomcat的那种

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class WebserviceApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(WebserviceApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {

        //  这里sources的类就是启动类
        return builder.sources(WebserviceApplication.class);
    }
}

接下来写客户端
需求是定时检查固定目录是否有当天文件,没有的话发送请求到服务端请求文件

你可能感兴趣的:(WebService)