1

我用 Java 编写了一个线程程序来从 URL (https) 下载文件。有时,下载的文件的大小会从其原始大小减小。

如何在不丢失数据的情况下下载文件?

代码

public class Download extends Observable implements Runnable {
    private static final int MAX_BUFFER_SIZE = 1024;        
    public static final int DOWNLOADING = 0;    
    public static final int PAUSED = 1; 
    public static final int COMPLETE = 2;   
    public static final int CANCELLED = 3;  
    public static final int ERROR = 4;  
    private URL url; 
    private int size; 
    private int downloaded; 
    private int status; 
    
    public Download(URL url){
        this.url = url;
        size=-1;
        downloaded=0;
        status=DOWNLOADING;
        download();
    }
    
    public String getURL(){
        return url.toString();
    }   
    
    public void error(){
        status = ERROR;
        stateChanged();
    }
    
    private void download(){
        Thread thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {     
        RandomAccessFile randomAccessFile = null;
        InputStream inputStream = null;
        try{
            HttpsURLConnection connection = getSSLCertficate(getURL());
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Range","bytes=" + downloaded + "-");
            connection.connect();
            if(connection.getResponseCode()/100 != 2){
                error();
            }
            int contentLength = connection.getContentLength();
            if(contentLength <1){
                error();
            }
            if(size == -1){
                size = contentLength;
                stateChanged();
            }
            randomAccessFile = new RandomAccessFile("/home/user/Desktop/dotproject-2.1.5.tar.gz","rw");         
            randomAccessFile.seek(downloaded);
            inputStream = connection.getInputStream();
            while(status == DOWNLOADING){
                byte buffer[];
                int finalSize=size - downloaded;
                if ( finalSize > MAX_BUFFER_SIZE) {
                    buffer = new byte[MAX_BUFFER_SIZE];
                } else {
                    buffer = new byte[size - downloaded];
                }
                int read = inputStream.read(buffer);
                if(read == -1)
                    break;              
                
                randomAccessFile.write(buffer, 0, read);                
                downloaded += read;             
                stateChanged();
            }           
            
        }catch (Exception e) {
            
        }
    }
    
    private void stateChanged(){
        setChanged();
        notifyObservers();
    }
    
    private HttpsURLConnection getSSLCertficate(String urlPath) throws NoSuchAlgorithmException, KeyManagementException, IOException{
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0],new TrustManager[]{new DefaultTrustManager()},new SecureRandom());
        SSLContext.setDefault(ctx);
        
        URL url = new URL(urlPath);
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setHostnameVerifier(new HostnameVerifier() {
            
            @Override
            public boolean verify(String arg0, SSLSession arg1) {               
                return true;
            }
        });
        
        return conn;
    }

    public static void main(String[] args) throws MalformedURLException {
        Download d = new Download(new URL("https://192.16.1.130/Source.tar.gz"));
        d.run();
    }

}
4

2 回答 2

1

请在 finally 部分关闭您的输入流(而不是自动刷新所有数据):

try {
    ....
} catch(...) {
    ...
} finally {
    // This will guaranty you get all data:
    inputStream.close();
}
于 2012-05-25T07:08:54.750 回答
0

你太复杂了。这是如何复制字节流,任何字节流。

int count;
byte[] buffer = new byte[8192]; // you can tune this value
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

您不需要大小为预期输入长度的缓冲区;您甚至不需要知道HttpURLConnection.

于 2012-05-25T10:32:15.050 回答