package com.coderising.download.impl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import com.coderising.download.api.Connection;
import com.coderising.download.api.ConnectionException;
//非public class,仅包内可见,依靠ConnectionMangerImpl实现
class ConnectionImpl implements Connection {
URL url;
static final int BUFFER_SIZE = 1024;
ConnectionImpl(String _url) throws ConnectionException {
try {
this.url = new URL(_url);
} catch (MalformedURLException e) {
throw new ConnectionException(e);
}
}
/*
* 分段读取数据
* @see com.coderising.download.api.Connection#read(int, int)
*/
@Override
public byte[] read(int startPos, int endPos) throws IOException {
/*
* HttpURLConnection是基于HTTP协议的,HttpURLConnection的对象不能直接构造,需要通过url.openConnection()来获得HttpURLConnection对象
* 示例如下:
* String slurl = "http://....";
* URL url = new URL(slurl);
* HttpURLConnection httpCoon = (HttpURLConnection) url.openConnection();
* 调用HttpURLConnection连接对象的getInputStream()函数,将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端
*/
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestProperty("Range","bytes=" + startPos + "-" + endPos); //只发一个特定的片段,比is.skip有效
InputStream is = httpConn.getInputStream();// 注意,实际发送请求的代码段就在这里 -------------------------------输入流
//is.skip(startPos);//跳过startPos之前的内容
byte[] buff = new byte[BUFFER_SIZE];//buff是搬运工
int totalLen = endPos - startPos + 1; //注意+1
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节数组流, 可以捕获内存缓冲区的数据,转换成字节数组。----输出流
while(baos.size() < totalLen){
int len = is.read(buff);//从输入流中读取数据到buff数组,同时返回读取长度,每次读取量小于等于1024
if (len < 0){
break;
}
baos.write(buff, 0, len);//buff数组中的数据写入输出流
}
if(baos.size() > totalLen){
byte[] data = baos.toByteArray();
return Arrays.copyOf(data, totalLen);
}
return baos.toByteArray();
}
/*
* 获取资源长度
* @see com.coderising.download.api.Connection#getContentLength()
*/
@Override
public int getContentLength() {
URLConnection con;
try {
con = url.openConnection();
return con.getContentLength();
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}
@Override
public void close() {
}
}