Socket编程:下载文件

package socket;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Client
{
	public static void main(String[] args) throws Exception
	{
		Socket client = new Socket("dlsw.baidu.com", 80);
		client.setSoTimeout(10000);

		StringBuilder sb = new StringBuilder();
		
		// HTTP协议中的换行符为CRLF,即\r\n,每一行请求消息头都需要以其结尾
		sb.append("GET /sw-search-sp/soft/2e/10849/wrar521sc_setup.1426841415.exe HTTP/1.1\r\n");
		sb.append("Host: dlsw.baidu.com\r\n");
		sb.append("Connection: keep-alive\r\n");
		sb.append("Accept: */*\r\n");
		sb.append("User-Agent: JavaSocket\r\n");
		
		// 消息头结束需要单独一行CRLF
		sb.append("\r\n");
		OutputStream os = client.getOutputStream();
		InputStream is = client.getInputStream();
		os.write(sb.toString().getBytes("UTF-8"));
		os.flush();

		// 保存文件路径
		File file = new File("D:/Setups/wrar521sc_setup.1426841415.exe");
		FileOutputStream fos = new FileOutputStream(file);
		String line = null;
		long contentLength = 0;

		// HTTP协议中的换行符为CRLF,即\r\n,读取到单独的一行\r\n意味着消息头读取完毕。
		while (!"\r\n".equals(line))
		{
			line = readLine(is);

			if (line.startsWith("Content-Length"))
			{
				contentLength = Long.parseLong(line.split(":")[1].trim());
			}

			System.out.print(line);
		}

		saveBody(is, contentLength, fos);
		System.out.println("File download complete.");

		// 应该在try-catch的finally块中关闭,为了减少篇幅写简单点。
		client.close();
		is.close();
		fos.close();
	}

	/**
	 * 从socket的输入流中按行读取消息头
	 * @param is 输入流
	 * @return 每行字符串
	 * @throws Exception 
	 */
	private static String readLine(InputStream is) throws Exception
	{
		List<Byte> lineBytes = new ArrayList<Byte>();
		int readByte = 0;

		while (true)
		{
			readByte = is.read();
			lineBytes.add(new Byte((byte) readByte));

			if (10 == readByte)
			{
				// \r\n 分别为13、10,读取到10意味着换行,跳出循环
				break;
			}
		}

		byte[] bytes = new byte[lineBytes.size()];
		
		for (int i = 0; i < lineBytes.size(); i++)
		{
			bytes[i] = lineBytes.get(i).byteValue();
		}

		return new String(bytes);
	}

	/**
	 * 保存消息体的字节流到文件中。
	 * @param is socket的输入流
	 * @param contentLength response中返回的消息体长度
	 * @param fos 文件输出流
	 * @throws Exception
	 */
	private static void saveBody(InputStream is, long contentLength,
			FileOutputStream fos) throws Exception
	{
		long totalRead = 0;
		byte[] bytes = new byte[512];
		while (totalRead < contentLength)
		{
			int read = is.read(bytes);
			totalRead += read;

			// 这里不能直接使用fos.write(bytes),因为即使除了最后一次,前面也不是每次读取的长度都为512(数组长度),一定要根据每次读取的长度写入输出流
			fos.write(bytes, 0, read);
		}

		fos.flush();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值