`
tjc
  • 浏览: 66825 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
收藏列表
标题 标签 来源
支持断点续传的上传类,并支持分布式,随机获取服务器 断点续传, 上传, 分布式 自由教育网
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Random;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;


/**
 * 文件上传类,支持任何格式,并支持断点续传
 * @author <a href="mailto:zhsj0110@163.com">zhoushijun</a>
 *
 */
public class UploadUtils implements Runnable {

	private String downloadUrl = null;
	private String nextURL = null;

	private String SSIC = null;
	private final String BOUNDARY = "eba5ba3d948f4ef0b107";
	private final int SIZE = 50000;
	private final String PRAGMA = "xz4BBcVF923244C-0141-4DF2-9D65-47BED8C75931200961516583401660--eba5ba3d948f4ef0b107";
	private int numOfCycle;
	private long fileSize;

	private FileInputStream fis;
	private Log log = LogFactory.getLog(UploadUtils.class);
	private String downloadPath = "c:/result.jpg";

	private int getRandom(int size) {
		Random rand = new Random();
		return Math.abs(rand.nextInt()) % size;
	}

	private String getDownloadURL(String result) throws DocumentException {
		log.info("result=" + result);
		Document doc = DocumentHelper.parseText(result);
		Node node = doc.selectSingleNode("/results/uri");
		return node.valueOf("@download");
	}

	/**
	 * 支持断点续传
	 * 
	 * @param uploadFile
	 *            需要上传的文件,可以是struts2上传中的temp文件,如果传入的文件是struts2的temp文件,则必须传参数filePath和fileName,文件名称将以filePath为准
	 * @param filePath
	 *            上传后文件存放的路径,从/tab_new/之后的地址(上传到媒体后会上传到tab_new的虚拟目录下),不包含文件名称
	 * @param fileName
	 *            上传后文件被重命名的文件名,如果此为空,则取uploadFile.getName()的值
	 * @return
	 * @throws DocumentException
	 * @throws BusinessException
	 * @throws IOException
	 */
	public synchronized String uploadFileResume(File uploadFile,
			String filePath, String fileName) throws DocumentException,
			BusinessException, IOException {

		String uploadUri = "/BlockUploadFile.aspx";
		String downloadURL = null;
		int random = getRandom(Global.mediaMap.size());
		String mediaServerUrl = Global.mediaMap.get(random) + uploadUri;
//		String mediaServerUrl = "http://10.10.20.74:8088/" + uploadUri;
		try {
			fis = new FileInputStream(uploadFile);
			downloadURL = this.uploadFileResume(uploadFile, null,
					mediaServerUrl, filePath, fileName);

		} catch (IOException e) {

			log.error(mediaServerUrl, e);

			for (int i = 0; i < Global.mediaMap.size(); i++) {
				mediaServerUrl = Global.mediaMap.get(random) + uploadUri;
				try {
					downloadURL = this.uploadFileResume(uploadFile, null,
							mediaServerUrl, filePath, fileName);
				} catch (Exception ex) {

					log.error(mediaServerUrl, ex);
					continue;
				}
			}
		} finally {
			if (null != fis) {
				fis.close();
			}
		}
		if (null == downloadURL || "".equals(downloadURL)) {
			throw new BusinessException(
					"Media Server error , or can not return a valid URL");
		}
		return this.getDownloadURL(downloadURL);
	}

	/**
	 * Resume broken transfer 断点续传
	 * 
	 * @param uploadFile
	 *            需要上传的文件,不可以是struts2上传中的temp文件,必须有正确的后缀名
	 * @return
	 * @author zhoushijun
	 * @throws DocumentException
	 * @throws BusinessException
	 * @throws IOException
	 * @since 2009-11-5
	 */
	public synchronized String uploadFileResume(File uploadFile)
			throws DocumentException, BusinessException, IOException {

		return this.uploadFileResume(uploadFile, null, null);
	}

	/**
	 * 
	 * @param uploadFile
	 *            需要上传的文件,支持断点续传
	 * @param ssic
	 *            该值可以不提供 调用的时候传入null
	 * @param signal
	 *            表示是否需要同时下载的标志 ,如果只是上传, signal=0, 如果上传的同时还在下载,signal=1
	 * @param serverUrl
	 *            媒体服务器的url地址
	 * @param filePath
	 *            上传后文件存放的路径,从/tab_new/之后的地址(上传到媒体后会上传到tab_new的虚拟目录下),不包含文件名称
	 * @param fileName
	 *            上传后文件被重命名的文件名,如果此为空,则取uploadFile.getName()的值
	 * @return 下载文件的地址
	 * @throws IOException
	 */
	private String uploadFileResume(File uploadFile, String ssic,
			String serverUrl, String filePath, String fileName)
			throws IOException {

		String returnString = null;
		try {
			if (ssic != null && !ssic.trim().equals("")) {
				SSIC = ssic;
			}

			String urlAddress = serverUrl;
			fileSize = uploadFile.length();

			log.info("upload file size : " + fileSize);
			numOfCycle = (int) (fileSize % (SIZE + 1) == 0 ? fileSize
					/ (SIZE + 1) : fileSize / (SIZE + 1) + 1);

			int flag = 0;
			for (int i = 0; i < numOfCycle; i++) {
				URL url = null;
				if (i == 0) {
					url = new URL(urlAddress);
				} else {
					url = new URL(nextURL);
				}

				log.info("upload url : " + url);
				HttpURLConnection httpConn = (HttpURLConnection) url
						.openConnection();
				httpConn.setDoOutput(true);
				httpConn.setDoInput(true);
				httpConn.setRequestMethod("POST");
				httpConn.setRequestProperty("Host", "");

				httpConn.setRequestProperty("Cookie", "ssic=" + SSIC);
				httpConn.setRequestProperty("Accept-Encoding", "identity");
				byte[] buffer = new byte[(int) SIZE + 1];
				httpConn.setRequestProperty("Content-Type",
						"multipart/form-data; boundary=" + BOUNDARY);
				httpConn.setRequestProperty("Pragma", PRAGMA);
				
				if( null !=filePath && !"".equals(filePath)) {
					httpConn.setRequestProperty("filePath", filePath);
				}

				DataOutputStream out = null;
				if (i == numOfCycle - 1) {
					log.info("Range = "+((int) (i * SIZE) + flag) + "-" + ((int) ((i + 1) * SIZE) + flag));
					httpConn.setRequestProperty("Range", "bytes="
							+ ((int) (i * SIZE) + flag) + "-" + (fileSize - 1));
					
				} else {
					log.info("Range = "+((int) (i * SIZE) + flag) + "-" + ((int) ((i + 1) * SIZE) + flag));
					httpConn.setRequestProperty("Range", "bytes="
							+ ((int) (i * SIZE) + flag) + "-"
							+ ((int) ((i + 1) * SIZE) + flag));
					
				}
				int len = fis.read(buffer);

				flag++;
				try {
					out = new DataOutputStream(httpConn.getOutputStream());
					out.write(("--" + BOUNDARY + "\r\n").getBytes("UTF-8"));

					out
							.write(("Content-Disposition:form-data;name=\"UploadFile\";filename=\""
									+ (null == fileName ? uploadFile.getName()
											: fileName) + "\"\r\n")
									.getBytes("UTF-8"));

					out.write("Content-Type:image/gif\r\n\r\n"
							.getBytes("UTF-8"));
					out.write(buffer, 0, len);

					out.write(("\r\n--" + BOUNDARY + "\r\n").getBytes("UTF-8"));

					InputStream inStream = httpConn.getInputStream();
					if (i == 0) {
						byte[] returnBuffer = new byte[10240];
						int length = inStream.read(returnBuffer);
						returnString = new String(returnBuffer, 0, length,
								"UTF-8");
						String firstProcessedStr = returnString
								.substring(returnString.indexOf("http:"));
						String secondProcessedStr = firstProcessedStr
								.substring(0, firstProcessedStr.indexOf("\""));
						nextURL = serverUrl
								+ secondProcessedStr
										.substring(secondProcessedStr
												.indexOf("?"));
						String firstStr = returnString.substring(returnString
								.indexOf("download=") + 10);
						downloadUrl = firstStr.substring(0, firstStr
								.indexOf("\""));
					}
					inStream.close();
					out.flush();
				} catch (Exception e) {
					log.error("", e);
					throw new RuntimeException(e);
				} finally {
					if (null != out) {
						out.close();
					}
				}

				// if (signal == 1 && i == 0) {
				// try {
				// Thread thread = new Thread(this);
				// thread.start();
				// } catch (Exception e) {
				// log.error("start file upload thread exception.", e);
				// }
				// }
			}
			// fis.close();
		} catch (Exception e) {
			log.error("Media server return:" + returnString);
			throw new RuntimeException(e);
		}

		return returnString;
	}

	public void downloadFile() throws Exception {
		File downloadFile = new File(downloadPath);
		FileOutputStream fos = new FileOutputStream(downloadFile);
		int flag = 0;
		for (int i = 0; i < numOfCycle; i++) {
			int statusCode = request(flag, i);

			while (statusCode == 416) {
				Thread.sleep(50);
				statusCode = request(flag, i);
			}
			flag++;
		}
		fos.flush();
		fos.close();
	}

	/**
	 * @param flag
	 * @param i
	 * @return
	 * @throws MalformedURLException
	 * @throws IOException
	 * @throws ProtocolException
	 */
	private int request(int flag, int i) throws MalformedURLException,
			IOException, ProtocolException {
		HttpClient httpClient = new HttpClient();
		PostMethod postMethod = new PostMethod(downloadUrl);
		postMethod.setRequestHeader("Cookie", "ssic=" + SSIC);
		if (i == numOfCycle - 1) {
			postMethod.setRequestHeader("Range", "bytes="
					+ ((int) (i * SIZE) + flag) + "-" + (fileSize - 1));

		} else {
			postMethod.setRequestHeader("Range", "bytes="
					+ ((int) (i * SIZE) + flag) + "-"
					+ ((int) ((i + 1) * SIZE) + flag));
		}
		int statusCode = httpClient.executeMethod(postMethod);
		String range = getValue(postMethod.getResponseHeader("Range"));
		range = range.substring(range.indexOf("=") + 1);

		String[] rangearea = range.split("-");
		long rangeStart = Long.parseLong(rangearea[0]);
		// long rangeEnd = 0;
		// if (rangearea.length == 2) {
		// rangeEnd = Long.parseLong(rangearea[1]);
		// }
		if (statusCode == HttpStatus.SC_OK) {
			InputStream stream = postMethod.getResponseBodyAsStream();
			DataInputStream in = new DataInputStream(stream);
			File savedFile = new File(downloadPath);
			RandomAccessFile oSavedFile = new RandomAccessFile(savedFile, "rw");
			byte[] inc = new byte[1024];
			int insize = 0;
			oSavedFile.seek(rangeStart);
			while ((insize = in.read(inc)) != -1) {
				oSavedFile.write(inc, 0, insize);
			}
			oSavedFile.close();
			in.close();
		}
		return statusCode;
	}

	public static String getValue(Object obj) {
		if (obj == null || "null".equals(obj)) {
			return "";
		} else {
			return obj.toString().trim();
		}
	}

	public void run() {
		try {

			downloadFile();

		} catch (Exception e) {
			log.error("invoke download file method exception.", e);
		}

	}

}
ssasasa
ssssssss
Global site tag (gtag.js) - Google Analytics