package com.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

public static void main(String[] args) {
    String url = "https://youku163.zuida-bofang.com/20181001/16086_4fce2677/800k/hls/index.m3u8";
    List<String> tsList = getTSPathByM3U8(url);
    String basePath = url.substring(0, url.lastIndexOf("/") + 1);
    for (String tsPath : tsList) {
        download(basePath + tsPath);
    }
    mergeFile(System.getProperty("user.dir") + File.separator + "tmp");
}

/**
 * 下载资源
 * 
 * @param urlStr
 */
public static void download(String urlStr) {
    try {
        URL url = new URL(urlStr);
        String urlPath = url.getPath();
        String fileName = "";
        if (urlPath.lastIndexOf("/") >= 0)
            fileName = urlPath.substring(urlPath.lastIndexOf("/") + 1);
        else
            fileName = urlPath;
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

// 设置超时时间

        connection.setConnectTimeout(60 * 1000);
        // 连接成功,开始下载文件
        if (connection.getResponseCode() == 200) {
            // 在当前运行目录下建立临时目录,存放临时文件
            File tmpDir = new File(System.getProperty("user.dir") + File.separator + "tmp");
            if (!tmpDir.exists())
                tmpDir.mkdir();
            File file = new File(tmpDir.getAbsolutePath() + File.separator + fileName);
            if (file.exists() && fileIsUsed(file)) {
                // 文件存在且被占用
                return;
            } else {
                file.createNewFile();
            }
            // 开始下载
            InputStream is = connection.getInputStream();
            int ContentLength = connection.getContentLength();
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int i, length = 0;
            while ((i = is.read(buffer)) != -1) {
                length += i;
                System.out.println(fileName + "\t正在下载(" + length + "/" + ContentLength + ")");
                fos.write(buffer);
            }
            fos.flush();
            is.close();
            fos.close();
            System.out.println(fileName + "\t下载完成");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * 从m3u8文件中解析出ts文件位置
 * 
 * @param m3u8_Path
 * @return
 */
public static List<String> getTSPathByM3U8(String m3u8_Path) {
    try {
        System.out.println("开始访问m3u8文件并解析内容");
        HttpURLConnection connection = (HttpURLConnection) new URL(m3u8_Path).openConnection();

// 设置超时时间

        connection.setConnectTimeout(60 * 1000);
        List<String> list = new ArrayList<String>();
        String charSet = getCharSet(connection.getContentType());
        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), charSet));
        String line;
        while ((line = br.readLine()) != null) {
            if (line.contains("ts"))
                list.add(line);
        }
        br.close();
        System.out.println("m3u8文件解析成功");
        return list;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * 合并ts文件
 * 
 * @param dirPath
 */
public static void mergeFile(String dirPath) {
    File dir = new File(dirPath);
    if (!dir.exists() || !dir.isDirectory()) {
        System.out.println("文件目录不存在或不是文件夹");
        return;
    }
    File mergeFile = new File(dir.getParent() + File.separator + System.currentTimeMillis() + ".ts");
    try {
        mergeFile.createNewFile();
    } catch (IOException e) {
        System.out.println("创建合并文件失败");
    }
    File[] tsFiles = orderByName(dir.listFiles());
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(mergeFile);
        for (File file : tsFiles) {
            fis = new FileInputStream(file);
            int i = 0;
            byte[] buffer = new byte[1024];
            while ((i = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, i);
            }
            System.out.println(file.getName() + "合并成功");
        }
        fis.close();
        fos.close();
        System.out.println("------------------合并成功------------------");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 根据文件名称进行文件的排序
 * 
 * @param files
 * @return
 */
private static File[] orderByName(File[] files) {
    List<File> fileList = Arrays.asList(files);
    Collections.sort(fileList, new Comparator<File>() {
        @Override
        public int compare(File f1, File f2) {
            if (f1.isDirectory() && f2.isFile())
                return -1;
            if (f1.isFile() && f2.isDirectory())
                return 1;
            return f1.getName().compareTo(f2.getName());
        }
    });
    return files;
}

/**
 * 打印连接基本信息
 * 
 * @param conn
 */
private void printConnInfo(HttpURLConnection conn) {
    try {
        System.out.println("状态码:" + conn.getResponseCode());
        System.out.println("状态信息:" + conn.getResponseMessage());
    } catch (IOException e) {
        e.printStackTrace();
    }
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println("服务器时间:" + sdf.format(new Date(conn.getDate())));
    System.out.println("服务器:" + conn.getHeaderField("Server"));
    System.out.println("文件类型:" + conn.getContentType());
    System.out.println("文件大小:" + conn.getContentLength());
    URL url = conn.getURL();
    System.out.println("网址:" + url.getHost());
    System.out.println("路径:" + url.getPath());
    String urlPath = url.getPath();
    String fileName = "";
    if (urlPath.lastIndexOf("/") >= 0)
        fileName = urlPath.substring(urlPath.lastIndexOf("/") + 1);
    else
        fileName = urlPath;
    System.out.println("文件名:" + fileName);
}

/**
 * 获取字符编码
 * 
 * @param str
 * @return
 */
private static String getCharSet(String str) {
    String charset = "UTF-8";
    Pattern pattern = Pattern.compile("charset=\\S*");
    Matcher matcher = pattern.matcher(str);
    if (matcher.find()) {
        charset = matcher.group().replace("charset=", "");
    }
    return charset;
}

/**
 * 判断文件是否被占用
 * 
 * @param file
 * @return
 */
private static boolean fileIsUsed(File file) {
    try {
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        raf.close();
        System.out.println("文件未被使用");
        return false;
    } catch (Exception e) {
        System.out.println("文件被占用");
    }
    return true;
}

}

## 首先安装centos7.2 ##

因为我的博客部署在另一个centos容器里头,占用了8888,888,80,443,3306 等端口
所以这里端口对应 docker run -d -it -p 8889:8888 -p 81:80 -p 444:443 -p 3307:3306 -v /jenkins:/www --privileged=true  centos:7.2.1511


## 进入容器 ##

docker exec -it 5ebab2cd23b5 bash


## 安装jdk和tomcat ##

JDK版本:jdk-8u171-linux-x64.tar.gz
安装教程:https://www.cnblogs.com/Dylansuns/p/6974272.html
jdk下载地址:http://ghaffarian.net/downloads/Java/

Tomcat版本:apache-tomcat-8.5.30.tar.gz
Tomcat下载地址:http://archive.apache.org/dist/tomcat/tomcat-8/v8.5.30/bin/

一、Zuul简介

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

二、实现

1.加入依赖:zuul;
2.启动类加入@EnableZuulProxy
3.yml文件

1.png

三、编写代码

@Component
public class MyFilter extends ZuulFilter {

private static Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override
public String filterType() {
    return "pre";
}

@Override
public int filterOrder() {
    return 0;
}

@Override
public boolean shouldFilter() {
    return true;
}

@Override
public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
    Object accessToken = request.getParameter("token");
    if(accessToken == null) {
        log.warn("token is empty");
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(401);
        try {
            ctx.getResponse().getWriter().write("token is empty");
        }catch (Exception e){}

        return null;
    }
    log.info("ok");
    return null;
}

}


filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
pre:路由之前
routing:路由之时
post: 路由之后
error:发送错误调用
filterOrder:过滤的顺序
shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
————————————————