package org.springblade.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
 * 使用multipart/form-data格式传输文件到给定接口
 */
@Slf4j
public class SendFileUtil {

	private SendFileUtil() {
	}

	/**
	 * post请求提交form-data上传文件
	 *
	 * @param url     上传地址
	 * @param headers 请求头
	 * @param file    上传文件
	 * @return
	 */
	public static String doPostUploadFile(String url, Map<String, String> headers, File file) {
		HttpPost httpPost = new HttpPost(url);
		packageHeader(headers, httpPost);
		String fileName = file.getName();

		CloseableHttpResponse response = null;

		String respContent = null;

		long startTime = System.currentTimeMillis();

		// 设置请求头 boundary边界不可重复，重复会导致提交失败
		String boundary = "-------------------------" + UUID.randomUUID().toString();
		httpPost.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary);

		// 创建MultipartEntityBuilder
		MultipartEntityBuilder builder = MultipartEntityBuilder.create();
		// 设置字符编码
		builder.setCharset(StandardCharsets.UTF_8);
		// 模拟浏览器
		builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
		// 设置边界
		builder.setBoundary(boundary);
		// 设置multipart/form-data流文件
		builder.addPart("sendfile", new FileBody(file));
		builder.addTextBody("fileType", "1");
		// application/octet-stream代表不知道是什么格式的文件
		builder.addBinaryBody("media", file, ContentType.create("application/octet-stream"), fileName);

		HttpEntity entity = builder.build();
		httpPost.setEntity(entity);
		CloseableHttpClient httpClient = HttpClients.createDefault();
		try {
			response = httpClient.execute(httpPost);
			if (response != null && response.getStatusLine() != null && response.getStatusLine().getStatusCode() < 400) {
				HttpEntity he = response.getEntity();
				if (he != null) {
					respContent = EntityUtils.toString(he, "UTF-8");
				}
			} else {
				log.error("对方响应的状态码不在符合的范围内!");
				throw new RuntimeException();
			}
			return respContent;
		} catch (Exception e) {
			log.error("网络访问异常,请求url地址={},响应体={},error={}", url, response, e);
			throw new RuntimeException();
		} finally {
			log.info("统一外网请求参数打印,post请求url地址={},响应={},耗时={}毫秒", url, respContent, (System.currentTimeMillis() - startTime));
			try {
				if (response != null) {
					response.close();
				}
				if (null != httpClient) {
					httpClient.close();
				}
			} catch (IOException e) {
				log.error("请求链接释放异常", e);
			}
		}
	}

	/**
	 * 封装请求头
	 *
	 * @param paramsHeads
	 * @param httpMethod
	 */
	private static void packageHeader(Map<String, String> paramsHeads, HttpRequestBase httpMethod) {
		if (null != paramsHeads && paramsHeads.size() > 0) {
			Set<Map.Entry<String, String>> entrySet = paramsHeads.entrySet();
			for (Map.Entry<String, String> entry : entrySet) {
				httpMethod.setHeader(entry.getKey(), entry.getValue());
			}
		}
	}
}
