package communication;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
public class DownloadPart implements Runnable {
/** Status members */
private long size;
private long offset;
private long downloadedAmount;
private File file;
private DownloadResumer downloadResumer;
/** File output stream of this part */
private FileOutputStream fileOS = null;
/** Indicates if this download part faulty */
private boolean isFaulty = false;
private boolean isResuming = false;
private boolean isCompleted = false;
/**
* @return the size
*/
public long getSize() {
return size;
}
/**
* @return isFaulty
*/
public boolean isFaulty() {
return isFaulty;
}
public boolean isCompleted() {
return isCompleted;
}
/**
* @return the downloadedAmount
*/
public long getDownloadedAmount() {
return downloadedAmount;
}
/**
* Constructor
*
* @param size
* Part size
*/
public DownloadPart( DownloadResumer downloadResumer, File file, long offset, long size ) {
this.downloadResumer = downloadResumer;
this.file = file;
this.offset = offset;
this.size = size;
this.isCompleted = false;
}
@Override
public void run() {
try {
// Check resuming
if ( this.file.exists() ) {
Long off = this.file.length();
if ( off <= this.size ) {
this.isResuming = true;
this.offset += off;
this.downloadedAmount = off;
this.downloadResumer.addDownloadedAmount( this.downloadedAmount );
}
}
if ( downloadedAmount == size )
isCompleted = true;
else {
this.fileOS = new FileOutputStream( this.file, isResuming );
URL url = new URL( downloadResumer.getRootDownload().getUrl().replace( " ", "%20" ) );
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Specify what part of file to download
if ( this.offset > 0 )
conn.setRequestProperty( "Range", "bytes=" + offset + "-" );
conn.connect();
int responseCode = conn.getResponseCode();
if ( responseCode == HttpURLConnection.HTTP_OK
|| responseCode == HttpURLConnection.HTTP_PARTIAL ) {
byte[] tmp_buffer = new byte[ 4096 ];
InputStream is = conn.getInputStream();
int n;
while ( ( n = is.read( tmp_buffer ) ) > 0 && downloadedAmount < size ) {
if ( !downloadResumer.getRootDownload().getConnection().isConnected )
break;
if ( downloadResumer.getRootDownload().isCanceled() ) {
isFaulty = true;
break;
}
if ( downloadedAmount + n > size ) {
n = (int) ( size - downloadedAmount );
}
fileOS.write( tmp_buffer, 0, n );
fileOS.flush();
downloadedAmount += n;
downloadResumer.addDownloadedAmount( n );
// Wait if paused
while ( downloadResumer.getRootDownload().isPaused()
&& !downloadResumer.getRootDownload().isCanceled() )
Thread.sleep( 1000 );
}
fileOS.close();
if ( downloadedAmount == size )
isCompleted = true;
}
else {
throw new IllegalStateException( "HTTP response: " + responseCode );
}
}
}
catch ( Exception e ) {
isFaulty = true;
StringWriter sw = new StringWriter();
e.printStackTrace( new PrintWriter( sw ) );
System.out.println( sw.toString() );
}
finally {
if ( fileOS != null ) {
try {
fileOS.close();
}
catch ( IOException e ) {
// Ignore
}
}
if ( isFaulty ) {
this.file.delete();
}
}
}
}