package com.slodon.b2b2c.core.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.UUID;

/**
 * @Classname: FileUploadUtil
 * @Description: 上传文件工具类：https请求使用postUploadSSL，http使用postUpload。主逻辑参照：https://www.cnblogs.com/yfrs/p/uploadbyjavacode.html
 * @author: 流泪兔兔头
 */
public class FileUploadUtil {

    private static final Logger log = LoggerFactory.getLogger(FileUploadUtil.class);

    /**
     * @Title: postUploadSSL
     * @Description: https上传文件方法
     * @param url      请求接口
     * @param file     文件实体
     * @param fileName 文件名
     * @author: 流泪兔兔头
     */
    public static String postUploadSSL(String url, File file, String fileName) {
        StringBuilder result = new StringBuilder();
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
            URL console = new URL(url);
            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
            // 构建请求头
            conn.setRequestMethod("POST");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);

            // 设置输出流
            String newLine = "\r\n";
            String boundaryPrefix = "--";
            String boundary = "----" + UUID.randomUUID().toString();
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            OutputStream out = conn.getOutputStream();
            StringBuilder sb = new StringBuilder();

            // 构建请求体
            sb.append(newLine);
            sb.append(boundaryPrefix);
            sb.append(boundary);
            sb.append(newLine);
            String nameTmp = file.getName();
            String typeName = nameTmp.substring(nameTmp.lastIndexOf("."));
            sb.append("Content-Disposition: form-data; name=\"media\";filename=\"").append(fileName).append(typeName).append("\";filelength=").append(file.length());
            sb.append("Content-Type: application/octet-stream");
            sb.append(newLine);
            sb.append(newLine);

            out.write(sb.toString().getBytes());
            FileInputStream in = new FileInputStream(file);
            byte[] bufferOut = new byte[1024];
            int bytes = 0;
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            in.close();
            byte[] end_data = (newLine + boundaryPrefix + boundary + boundaryPrefix + newLine).getBytes();
            out.write(end_data);
            out.flush();
            out.close();

            // 配置SSL
            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            conn.connect();

            // 读取请求返回信息
            InputStream is = conn.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String ret = "";
            while ((ret = br.readLine()) != null) {
                if (!ret.trim().equals("")) {
                    result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
                }
            }
            log.info("recv - {}", result);
            conn.disconnect();
            br.close();
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件上传失败{}", e.getMessage());
        }
        return result.toString();
    }

    /**
     * @Title: TrustAnyTrustManager
     * @Description: SSL用证书信任管理器
     * @author: 流泪兔兔头
     */
    private static class TrustAnyTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }

    /**
     * @Title: TrustAnyHostnameVerifier
     * @Description: SSL用主机名验证
     * @author: 流泪兔兔头
     */
    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
}