package cn.base.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;


import sun.misc.BASE64Decoder;

@SuppressWarnings("all")
public class FTPUtil {
	public static Log logger = LogFactory.getLog(FTPUtil.class);

	private static FTPUtil ftpUtil = new FTPUtil();

	public static FTPUtil getInstance() {
		return ftpUtil;
	}

	public static void downLoadFile(String path, OutputStream toClient) {
		BufferedInputStream bis = null;
		InputStream is = null;
		try {
			if (path.toUpperCase().indexOf("FTP") != -1) {
				String tempUrl = path;
				tempUrl = tempUrl.replaceAll("\\\\", "/");
				URL url = new URL(tempUrl);
				is = url.openStream();
				bis = new BufferedInputStream(is);
				IOUtils.copy(bis, toClient);
				return;
			}
		} catch (Exception e) {
			logger.error("FTP下载图片出错", e);
		} finally {
			try {
				if (toClient != null) {
					toClient.flush();
					toClient.close();
				}
				if (is != null) {
					is.close();
				}
				if (bis != null) {
					bis.close();
				}
			} catch (IOException e) {
				logger.error("关闭FTP通道出错", e);
			}
		}
	}
	/**
	 * 获取ftp图片流
	 * @param path
	 * @return
	 */
	public static InputStream getFTPPictureIS(String path) {
		InputStream is = null;
		try {
			if (path.toUpperCase().indexOf("FTP") != -1) {
				String tempUrl = path;
				tempUrl = tempUrl.replaceAll("\\\\", "/");
				URL url = new URL(tempUrl);
				is = url.openStream();
				return is;
			}
		} catch (Exception e) {
			logger.error("FTP获取图片流出错", e);
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				logger.error("关闭FTP通道出错", e);
			}
		}
		return is;
	}
	public static byte[] getFTPPictureBytes(String path) {
		byte[] bytes ;
		InputStream is = null;
		try {
			if (path.toUpperCase().indexOf("FTP") != -1) {
				String tempUrl = path;
				tempUrl = tempUrl.replaceAll("\\\\", "/");
				URL url = new URL(tempUrl);
				is = url.openStream();
				return StreamUtil.stream2Byte(is);
			}
		} catch (Exception e) {
			logger.error("FTP获取图片流出错", e);
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				logger.error("关闭FTP通道出错", e);
			}
		}
		bytes = new byte[0];
		return bytes;
	}

	//ftp图片上传，图片参数为base64封装的String
	public static boolean uploadFile(FTPUrl ftpUrl, String path, String filename, String inputImg) throws Exception {
		boolean flag = true;
		FTPClient ftpClient = null;
		ByteArrayInputStream input = null;
		try {
			if(inputImg==null) return false;
			//base64解码
			BASE64Decoder decoder = new BASE64Decoder();
			byte[] b_img = decoder.decodeBuffer(inputImg);
			/*
			//测试图片保存到本地--start*******************
			OutputStream out = new FileOutputStream("D:\\Program Files\\22.jpg");
			out.write(b_img);
			out.flush();
			out.close();
			//测试图片保存到本地--end*******************
			*/
			input = new ByteArrayInputStream(b_img);
			ftpClient = connectServer(ftpUrl);
			//new ByteArrayInputStream
			if (ftpClient.isConnected()) {
				changeWorkingDirectory(ftpClient, path);
				flag = ftpClient.storeFile(filename, input);
				if (flag) {
					logger.info("FTP上传文件成功！");
				} else {
					flag = false;
					logger.info("FTP上传文件失败！");
				}
			}
		} catch (Exception e) {
			 flag = false;
			logger.error("FTP文件上传失败！", e);
			throw e;
		} finally {
			input.close();
			closeConnect(ftpClient);
		}
		return flag;
	}
	/**
	 * 上传文件至ftp
	 * @param ftpUrl
	 * @param path
	 * @param filename
	 * @param input
	 * @return
	 * @throws Exception
	 */
	public static boolean uploadFile(FTPUrl ftpUrl, String path, String filename, InputStream input) throws Exception {
		boolean flag = true;
		FTPClient ftpClient = null;
		try {
			ftpClient = connectServer(ftpUrl);
			if (ftpClient.isConnected()) {
				changeWorkingDirectory(ftpClient, path);
				flag = ftpClient.storeFile(filename, input);
				if (flag) {
					logger.info("FTP上传文件成功！");
				} else {
					logger.info("FTP上传文件失败！");
				}
			}
			input.close();
		} catch (IOException e) {
			logger.error("FTP文件上传失败！", e);
			throw e;
		} catch (Exception e) {
			logger.error("FTP文件上传失败！", e);
			throw e;
		} finally {
			input.close();
			closeConnect(ftpClient);
		}
		return flag;
	}

	/*
	 * 得到配置文件中的FTP服务器地址
	 */
	public static String getFtpUrl(FTPUrl ftpUrl) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("ftp://");
		if (ftpUrl.getFtpUser() != null && ftpUrl.getFtpUser().trim().length() > 0) {
			buffer.append(ftpUrl.getFtpUser());
			buffer.append(":");
			buffer.append(ftpUrl.getFtpUserPassword());
			buffer.append("@");
		}
		buffer.append(ftpUrl.getFtpIp());
		if (ftpUrl.getFtpPort() != null) {
			buffer.append(":");
			buffer.append(ftpUrl.getFtpPort());
		}
		buffer.append("/");
		return buffer.toString();
	}

	/**
	 * @description 删除ftp上的文件
	 * @author sunw
	 * @param ftpUrl
	 * @return
	 * @throws Exception
	 */
	public static boolean deleteFileFromFtpUrl(String ftpUrl) throws Exception {
		boolean flag = false;
		if (null == ftpUrl || ftpUrl.trim().equals("")) {
			throw new Exception("ftpUrl串为空");
		}
		Map<String, String> result = getFtpInfoMapByFullPath(ftpUrl);
		String ftpUser = result.get("ftpUser");
		String ftpPassword = result.get("ftpPassword");
		String ftpIp = result.get("ftpIp");
		String ftpPort = result.get("ftpPort");
		String fileName = result.get("fileName");
		String path = result.get("path");
		FTPUrl ftp = FTPUtil.getFtpUrlObj(ftpIp, ftpPort, ftpUser, ftpPassword);
		FTPClient ftpClient = connectServer(ftp);
		if (null == ftpClient) {
			throw new Exception("ftp登录失败 ");
		} else {
			String fullPath = (null == path || "".equals(path.trim())) ? fileName : (path + "/" + fileName);
			try {
				flag = ftpClient.deleteFile(fullPath);
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
		return flag;

	}

	/**
	 * @author sunw 通过图片路径
	 *         获得ftpuser,ftppassword,ftpip,ftpport,在fpt上的文件路径,文件realname
	 * @param ftpUrlStr
	 * @return
	 * @throws Exception
	 */
	private static Map<String, String> getFtpInfoMapByFullPath(String ftpUrlStr) throws Exception {
		if (null == ftpUrlStr || "".equals(ftpUrlStr.trim())) {
			throw new Exception("ftpstr串为空");
		}
		ftpUrlStr = ftpUrlStr.replaceAll("\\\\", "/");
		ftpUrlStr = changeUrlCharater(ftpUrlStr);
		String array[] = ftpUrlStr.split("/");
		String[] ftpUserPasswordAndIpPort = array[2].split("@");
		String[] ftpUserAndPassword = ftpUserPasswordAndIpPort[0].split(":");
		String[] ftpIpAndPort = ftpUserPasswordAndIpPort[1].split(":");
		String ftpUser = ftpUserAndPassword[0];
		String ftpPassword = ftpUserAndPassword[1];
		String ftpIp = ftpIpAndPort[0];
		String ftpPort = ftpIpAndPort.length > 1 ? ftpIpAndPort[1] : "";
		String fileName = array[array.length - 1];// 获得文件名
		Map<String, String> resultMap = new HashMap<String, String>();
		resultMap.put("ftpUser", ftpUser);
		resultMap.put("ftpPassword", ftpPassword);
		resultMap.put("ftpIp", ftpIp);
		resultMap.put("ftpPort", ftpPort);
		resultMap.put("fileName", fileName);
		String path = "";
		for (int i = 3; i < array.length - 1; i++) {
			if (i != array.length - 2) {
				path += array[i] + "/";
			} else {
				path += array[i];
			}
		}
		resultMap.put("path", path);
		return resultMap;
	}

	public static void main(String[] args) {
		String temp = "ftp://xingwang:xingwang@172.16.62.131:21/20130829/755001.jpg";
		try {
//			boolean flag = deleteFileFromFtpUrl(temp);
//			System.out.println(flag);
		} catch (Exception e) {
			System.out.println("删除文件失败");
		}
		// String [] strSplit = temp.split("/");
		// for(int i = 0 ; i < strSplit.length ; i++) {
		// System.out.println(i+" = " + strSplit[i]);
		// }
	}

	public static String changeUrlCharater(String tempUrl) {
		tempUrl = tempUrl.replaceAll("%", "%25").replaceAll("#", "%23").replaceAll("\\+", "%2B").replaceAll("&", "%26");
		tempUrl = tempUrl.replaceAll("=", "%3D").replaceAll("\\?", "%3F");
		return tempUrl;
	}

	/**
	 * 连接到服务器
	 * 
	 * 
	 */
	private static FTPClient connectServer(FTPUrl ftpUrl) {
		FTPClient ftpClient = null;
		try {
			ftpClient = new FTPClient();
			ftpClient.setControlEncoding("GBK");
			if (ftpUrl.getFtpPort() != null) {
				ftpClient.setDefaultPort(ftpUrl.getFtpPort());
			}
			ftpClient.connect(ftpUrl.getFtpIp());
			ftpClient.login(ftpUrl.getFtpUser(), ftpUrl.getFtpUserPassword());
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			ftpClient.enterLocalPassiveMode();
			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
			ftpClient.setBufferSize(10240);
			int reply = ftpClient.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftpClient.disconnect();
				System.err.println("FTP server refused connection.");
				logger.info("FTP 服务拒绝连接！");
			}
		} catch (SocketException e) {
			logger.error("登录ftp服务器 " + ftpUrl.getFtpIp() + " 失败,连接超时！", e);
		} catch (IOException e) {
			logger.error("登录ftp服务器 " + ftpUrl.getFtpIp() + " 失败，FTP服务器无法打开！", e);
		}
		return ftpClient;
	}

	/**
	 * 关闭连接
	 */
	private static void closeConnect(FTPClient ftpClient) {
		try {
			if (ftpClient != null) {
				if (ftpClient.isConnected() == true) {
					ftpClient.logout();
				}
				ftpClient.disconnect();
			}
		} catch (Exception e) {
			logger.error("关闭ftp连接失败", e);
		}
	}

	/**
	 * 进入到服务器的某个目录下
	 * 
	 * @param directory
	 */
	private static void changeWorkingDirectory(FTPClient ftpClient, String directory) throws Exception {
		try {
			ftpClient.changeWorkingDirectory("/");
			String[] subPathArray = directory.split("/");
			for (String subPath : subPathArray) {
				ftpClient.makeDirectory(subPath);
				ftpClient.changeWorkingDirectory(subPath);
			}
		} catch (IOException ioe) {
			logger.error("改变ftp工作路径失败", ioe);
		}
	}

	/**
	 * 转码[ISO-8859-1 -> GBK] 不同的平台需要不同的转码
	 * 
	 * @param obj
	 * @return ""
	 */
	private static String iso8859togbk(Object obj) {
		try {
			if (obj == null)
				return "";
			else
				return new String(obj.toString().getBytes("iso-8859-1"), "GBK");
		} catch (Exception e) {
			return "";
		}
	}

	public static FTPUrl getFtpUrlObj(String ftpIp, String ftpPort, String ftpUser, String ftpPassword) {
		FTPUrl ftpUrl = new FTPUrl();
		ftpUrl.setFtpIp(ftpIp);
		if (ftpPort != null) {
			ftpUrl.setFtpPort(Integer.parseInt(ftpPort));
		}
		ftpUrl.setFtpUser(ftpUser);
		ftpUrl.setFtpUserPassword(ftpPassword);
		return ftpUrl;
	}

}
