All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mizhousoft.commons.download.DownloadThread Maven / Gradle / Ivy

package com.mizhousoft.commons.download;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.util.concurrent.TimeUnit;

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

import jakarta.servlet.http.HttpServletResponse;

/**
 * 下载线程
 *
 * @version
 */
class DownloadThread implements Runnable
{
	private static final Logger LOG = LoggerFactory.getLogger(DownloadThread.class);

	// 文件下载器
	private final HttpDownloader downloader;

	// 下载开始偏移
	private final ThreadStatusData statusData;

	// 连接超时时间,单位是毫秒
	private int connectTimeout;

	// 读取超时时间,单位是毫秒
	private int readTimeout;

	// 重试次数
	private int retry;

	// 重试延迟时间,单位是毫秒
	private long retryDelayTime;

	/**
	 * 构造函数
	 *
	 * @param statusData
	 * @param downloader
	 */
	public DownloadThread(ThreadStatusData statusData, HttpDownloader downloader)
	{
		this.statusData = statusData;
		this.downloader = downloader;
	}

	/**
	 * 执行线程
	 */
	@Override
	public void run()
	{
		try
		{
			execute();
		}
		catch (Throwable e)
		{
			LOG.error("Download part file failed.", e);
		}
		finally
		{
			downloader.countDown();
		}
	}

	/**
	 * 执行下载
	 * 
	 */
	private void execute()
	{
		// 下载是否成功
		boolean succeed = false;
		DownloadException cause = null;

		while (retry > 0)
		{
			if (isFinish())
			{
				succeed = true;
				break;
			}

			try
			{
				downownload();
				succeed = true;
				break;
			}
			catch (DownloadException e)
			{
				cause = e;
			}

			try
			{
				TimeUnit.MICROSECONDS.sleep(retryDelayTime);
			}
			catch (InterruptedException e)
			{
				LOG.error("Force to stop download file thread.");
				break;
			}

			retry = retry - 1;
		}

		if (succeed)
		{
			cause = null;
		}

		if (null != cause)
		{
			downloader.error(cause);
		}
	}

	/**
	 * 下载
	 * 
	 * @throws DownloadException
	 */
	private void downownload() throws DownloadException
	{
		RandomAccessFile raf = null;
		InputStream istream = null;
		HttpURLConnection conn = null;

		try
		{
			raf = new RandomAccessFile(downloader.getLocalTmpFile(), "rw");
			long startPos = statusData.getStartPosition();
			raf.seek(startPos);

			conn = downloader.openHttpURLConnection();

			// 获取下载输入流
			istream = getDownloadInputStream(conn);

			// 5 * 1024
			byte[] buffer = new byte[5120];
			int len = istream.read(buffer);
			while (len != -1)
			{
				raf.write(buffer, 0, len);
				statusData.incrementRead(len);

				len = istream.read(buffer);
			}
		}
		catch (DownloadException e)
		{
			throw e;
		}
		catch (Exception e)
		{
			throw new DownloadException("Download file failed.", e);
		}
		finally
		{
			DownloadUtils.closeStream(istream);
			DownloadUtils.closeFile(raf);

			if (null != conn)
			{
				conn.disconnect();
			}
		}
	}

	/**
	 * 获取下载输入流
	 * 
	 * @param conn
	 * @return
	 * @throws DownloadException
	 */
	private InputStream getDownloadInputStream(HttpURLConnection conn) throws DownloadException
	{
		try
		{
			conn.setConnectTimeout(connectTimeout);
			conn.setReadTimeout(readTimeout);

			long startPos = statusData.getStartPosition();
			long endPos = statusData.getEnd() - 1;

			String property = "bytes=" + startPos + "-" + endPos;
			conn.setRequestProperty("Range", property);

			int code = conn.getResponseCode();
			if (code != HttpServletResponse.SC_OK && code != HttpServletResponse.SC_PARTIAL_CONTENT)
			{
				throw new DownloadException("Server does not support mutil thread download.");
			}

			return conn.getInputStream();
		}
		catch (IOException e)
		{
			throw new DownloadException("Open download connection failed.", e);
		}
	}

	/**
	 * 下载是否完成
	 * 
	 * @return
	 */
	public boolean isFinish()
	{
		return statusData.isFinish();
	}

	/**
	 * 设置connectTimeout
	 * 
	 * @param connectTimeout
	 */
	public void setConnectTimeout(int connectTimeout)
	{
		this.connectTimeout = connectTimeout;
	}

	/**
	 * 设置readTimeout
	 * 
	 * @param readTimeout
	 */
	public void setReadTimeout(int readTimeout)
	{
		this.readTimeout = readTimeout;
	}

	/**
	 * 设置retry
	 * 
	 * @param retry
	 */
	public void setRetry(int retry)
	{
		this.retry = retry;
	}

	/**
	 * 设置retryDelayTime
	 * 
	 * @param retryDelayTime
	 */
	public void setRetryDelayTime(long retryDelayTime)
	{
		this.retryDelayTime = retryDelayTime;
	}

	/**
	 * 获取statusData
	 * 
	 * @return
	 */
	public ThreadStatusData getStatusData()
	{
		return statusData;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy