您的位置:首页 > 编程语言 > Java开发

【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】

2015-06-27 19:56 531 查看
[b]一、文件下载简述[/b]

  1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息

    (1)response.setContentType("application/force-download");

    (2)response.setContentLength(fis.available());

    (3)response.setHeader("Content-Disposition","attachment;filename="+filename);

  2.如果需要下载的文件名是中文,则还需要特殊对待

    (1)如果使用get方式向Servlet进行的请求,需要编码才能获取正确的文件名

      String filename=request.getParameter("filename");
      filename=new String(filename.getBytes("iso-8859-1"),"utf-8");

    (2)必须通知浏览器实际文件名是中文的,但是必须要经过编码才行。

      filename=URLEncoder.encode(filename,"utf-8");

      注:不经过编码的中文文件名能够成功下载,但是文件名是乱码。

  3.文件下载既能够是GET方式的请求,也可以是POST方式的请求。但是文件上传必须是GET方式的请求。

  4.使用多线程文件下载和断点下载都需要的核心类:RandomAccessFile类。

  API1.6对其描述为:   

   此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过
getFilePointer
方法读取,并通过
seek
方法设置。

   通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出
EOFException
(是一种
IOException
)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出
IOException
,而不是
EOFException
。需要特别指出的是,如果流已被关闭,则可能抛出
IOException


[b]二、单线程文件下载(网页上从服务器下载)[/b]

  1.JSP文件

<a href="<c:url value='/downloadFromServer?filename=动漫.jpg'/>">动漫.jpg下载</a><br/>


  2.Servlet响应请求

package com.kdyzm.multiplethreaddownload;
/*
* 这种方式是多线程下载的方式,但是这种方式的多线程和单线程并没有任何区别,甚至更耗时间,降低了效率
* 不应当适用这种方式
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

class Resource
{
public static final Object obj=new Object();
}
/*
* 该小练习演示多线程下载文件的方法与技巧。
*/
public class MultipleThreadDownload {
public static void main(String[] args) throws Exception {
String path="http://danbooru.donmai.us/data/8fc288b237cfcc0a8e026f79b65733ed.jpg";
//        String path="http://localhost:8080/day22_2/resource/video.mp4";
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//对connection对象进行一系列的设置处理。
conn.setRequestMethod("GET");//设置GET请求
conn.setDoInput(true);
conn.connect();
//获取状态码
int code=conn.getResponseCode();
System.out.println(code);
if(code==200)//如果请求成功,则开启多线程下载文件
{
String fileName="d://download/video.mp4";
long fileSize=conn.getContentLength();
RandomAccessFile out=new RandomAccessFile(new File(fileName),"rw");
out.setLength(fileSize);
System.out.println("文件的总大小为:"+fileSize);
long threadCount=8;//将会有四个线程参与多线程下载任务。
long threadPerDownloadSize=fileSize/threadCount+(fileSize%threadCount==0?0:1);
System.out.println("每个线程将会下载的数据量是:"+threadPerDownloadSize);
//下面计算每个具体的线程将会下载的数据量并创建线程对象开启线程下载。
for(long i=0;i<threadCount;i++)
{
//计算开始的字节
long start=i*threadPerDownloadSize;
long end=start+(threadPerDownloadSize-1);
System.out.println("第"+(i+1)+"个线程下载的内容为"+start+"-"+end);
new DownloadThread(out,url.toString(),start,end).start();
}
}
conn.disconnect();//连接断开
}
}
class DownloadThread extends Thread
{
private RandomAccessFile out;
private String url;
private long start;
private long end;
public DownloadThread(RandomAccessFile out, String url, long start, long end) {
this.url=url;
this.out=out;
this.start=start;
this.end=end;
}
//重写run方法。
@Override
public void run() {
synchronized(Resource.obj)
{
try {
HttpURLConnection conn=(HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setRequestProperty("range","bytes="+start+"-"+end);
conn.connect();

int code=conn.getResponseCode();
System.out.println("响应状态码为:"+code);

if(code==206)
{
long size=conn.getContentLength();
InputStream in=conn.getInputStream();
System.out.println("线程"+this.getName()+"下载的数据量为:"+size);
out.seek(start);
byte []buff=new byte[1024*1024];
int length=-1;
while((length=in.read(buff))!=-1)
{
out.write(buff, 0, length);
}
in.close();
}
conn.disconnect();//连接断开
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


MultipleThreadDownload.java
    曾经的博客中:/content/5539843.html 出现过这种错误。

  (2)为什么多线程下载文件的效率比单线程下载文件的效率更为低下?

    待续。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: