package org.loon.game.simple.download;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Copyright 2008 - 2009
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* [url]http://www.apache.org/licenses/LICENSE-2.0[/url]
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loonframework
* @author chenpeng
* @email:
[email protected]
* @version 0.1
*/
public class DownloadTool implements Runnable {
final static private Font font = new Font( "黑体", 0, 14);
private Rectangle rectangle;
final static private Image barImage = GraphicsUtils
.loadImage( "image/bar.png");
final static private int MAX_BUFFER_SIZE = 2048;
final static private int DOWNLOADING = 0;
final static private int PAUSED = 1;
final static private int COMPLETE = 2;
final static private int CANCELLED = 3;
final static private int ERROR = 4;
private Image backgroundBarImage;
private Image progressBarImage;
private Image dialogBarImage;
private URL url;
private int size;
private int downloaded;
private int contentLength;
private int status;
private DownloadListen listen;
private String downloadName;
/**
* 创建进度条提示框
*
* @param object
* @param w
* @param h
* @param filtrate
* @return
*/
private static Image createDialog(Image object, int w, int h,
boolean filtrate) {
Image barImage = null;
if (filtrate) {
barImage = GraphicsUtils.drawClipImage(object, 249, 30, 1, 57);
barImage = GraphicsUtils.transBlackColor(barImage);
} else {
barImage = GraphicsUtils.drawClipImage(object, 249, 27, 0, 0);
}
Image imageLeft = GraphicsUtils.drawClipImage(barImage, 8, 27, 0, 0);
Image imageRight = GraphicsUtils.drawClipImage(barImage, 8, 27, 241, 0);
Image ImageCenter = GraphicsUtils
.drawClipImage(barImage, 233, 27, 8, 0);
ImageCenter = GraphicsUtils.getResize(ImageCenter, w, h);
Graphics cg = ImageCenter.getGraphics();
cg.drawImage(imageLeft, 0, 0, null);
cg.drawImage(imageRight, w - 8, 0, null);
cg.dispose();
return ImageCenter;
}
/**
* 构造函数,加载指定url
*
* @param url
*/
public DownloadTool(String url) {
this.size = -1;
this.downloaded = 0;
this.status = DOWNLOADING;
try {
this.url = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
public DownloadTool(URL url) {
this.url = url;
this.size = -1;
this.downloaded = 0;
this.status = DOWNLOADING;
}
/**
* 设定进度条所在方位
*
* @param x
* @param y
* @param w
* @param h
*/
public void setRectangle( int x, int y, int w, int h) {
setRectangle( new Rectangle(x, y, w, h));
}
/**
* 设定进度条所在方位
*
* @param rectangle
*/
public void setRectangle(Rectangle rectangle) {
this.backgroundBarImage = GraphicsUtils.drawClipImage(barImage, 249,
27, 0, 0);
this.backgroundBarImage = createDialog(backgroundBarImage,
rectangle.width - 21, rectangle.height - 2, false);
// this.progressBarImage = GraphicsUtils.drawClipImage(barImage, 27, 27,
// 28, 28);
// this.progressBarImage = GraphicsUtils.drawClipImage(barImage, 27, 27,
// 56, 28);
this.progressBarImage = GraphicsUtils.drawClipImage(barImage, 27, 27,
0, 28);
this.dialogBarImage = createDialog(barImage, rectangle.width,
rectangle.height, true);
this.rectangle = rectangle;
}
/**
* 返回当前url地址
*
* @return
*/
public String getUrl() {
return url.toString();
}
/**
* 返回当前下载文件总长度
*
* @return
*/
public int getSize() {
return size;
}
/**
* 返回当前下载已完成长度
*
* @return
*/
public int getLevel() {
return downloaded;
}
/**
* 返回当前进度
*
* @return
*/
public int getProgress() {
return ( int) (( double) downloaded / ( double) size * 100);
}
public int getStatus() {
return status;
}
public void pause() {
status = PAUSED;
}
public void resume() {
status = DOWNLOADING;
download(listen);
}
public void cancel() {
status = CANCELLED;
}
private void error() {
status = ERROR;
}
public int getContentLength() {
return contentLength;
}
public void download(DownloadListen listen) {
this.listen = listen;
Thread thread = new Thread( this);
thread.start();
}
private String getFileName(URL url) {
String fileName = url.getFile();
return fileName.substring(fileName.lastIndexOf('/') + 1);
}
public String getFileName() {
return getFileName(url);
}
public boolean isExists() {
return new File(getFileName()).exists();
}
public String getDownloadName() {
return downloadName;
}
public void setDownloadName(String downloadName) {
this.downloadName = downloadName;
}
/**
* 进行文件下载并显示进度
*/
public void run() {
if (!isExists()) {
RandomAccessFile file = null;
InputStream stream = null;
try {
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestProperty( "Range", "bytes=" + downloaded
+ "-");
connection.connect();
if (connection.getResponseCode() / 100 != 2) {
error();
}
contentLength = connection.getContentLength();
if (contentLength < 1) {
error();
}
if (size == -1) {
size = contentLength;
}
file = new RandomAccessFile(getFileName(url), "rw");
file.seek(downloaded);
stream = connection.getInputStream();
while (status == DOWNLOADING) {
byte buffer[];
if (size - downloaded > MAX_BUFFER_SIZE) {
buffer = new byte[MAX_BUFFER_SIZE];
} else {
buffer = new byte[size - downloaded];
}
int read = stream.read(buffer);
if (read == -1) {
break;
}
file.write(buffer, 0, read);
downloaded += read;
listen.updateScreen();
}
if (status == DOWNLOADING) {
status = COMPLETE;
listen.call();
}
} catch (Exception e) {
error();
} finally {
if (file != null) {
try {
file.close();
file = null;
} catch (Exception e) {
}
}
if (stream != null) {
try {
stream.close();
stream = null;
} catch (Exception e) {
}
}
}
} else {
status = COMPLETE;
listen.call();
}
}
/**
* 绘制下载进度
*
* @param g
*/
public synchronized void draw(Graphics g) {
int progress = getProgress();
double ratio = ( double) (( double) getLevel() / ( double) getSize());
int offset = ( int) (rectangle.width * ratio);
g.drawImage(backgroundBarImage, rectangle.x + 19, rectangle.y, null);
g.drawImage(progressBarImage, rectangle.x + 1, rectangle.y,
offset + 20, rectangle.height - 2, null);
g.drawImage(dialogBarImage, rectangle.x, rectangle.y, null);
g.setFont(font);
String mes = (getDownloadName() + ",已完成进度 : " + progress + " %")
.intern();
FontMetrics fm = g.getFontMetrics();
int w = fm.stringWidth(mes);
int h = fm.getHeight() + 2;
g.setColor(Color.white);
GraphicsUtils.setRenderingHints(g);
g.drawString(mes, (rectangle.x + rectangle.width) / 2 - w / 2,
rectangle.y + h);
}
}