java - HTTP-Download - sometimes file is not downloaded complete without error -
i'm trying develope small java downloader. sometimes, can not find out when, 1 download missing few percent. after 1 download corrupt every download after corrupt. have no clue problem, , tried different output buffers no success. here source of download thread:
private void startdownload() { try { ins = null; outb=null; setrunning(true); // erstelle httpurlconnection objekt zur anfrage den server con = (httpurlconnection)url.openconnection(); con.setrequestmethod("get"); con.setrequestproperty("user-agent", datacontroller.getinstance().getuseragentstring()); if (datacontroller.getinstance().getcookie() != null) { con.setrequestproperty("cookie", datacontroller.getinstance().getcookie()); } system.out.println("saveto length: " + this.saveto ); system.out.println("loaded bytes : " + loadedbytes ); if (loadedbytes > 0) { // ist zieldatei noch vorhanden und stimmt die größe? if (saveto != null && saveto.exists() && saveto.length() == loadedbytes) { // save null!!! // wiederaufnahme-position übermitteln con.setrequestproperty("range", "bytes=" + loadedbytes + "-"); } else if (!saveto.exists()) { // zieldatei existiert nicht (mehr) try { if (!saveto.createnewfile()) { // zieldatei konnte nicht angelegt werden // saveto-objekt zurücksetzen und somit save-dialog provozieren saveto = null; } } catch (exception e) { // beim anlegen des files ist ein unerwarteter fehler aufgetreten e.printstacktrace(); // saveto-objekt zurücksetzen und somit save-dialog provozieren saveto = null; } } } con.connect(); // prüfe response-code rc = con.getresponsecode(); if (datacontroller.getinstance().isdebugmode()) system.out.println("rc " + rc); if (rc == httpurlconnection.http_ok || rc == httpurlconnection.http_partial) { // wenn keine 206 partial content kam, loaded-zähler zurücksetzen, download von vorne beginnen if (rc == httpurlconnection.http_ok) { loadedbytes = 0; } string filename = getfilename(); if (loadedbytes == 0) { size = long.valueof(con.getheaderfield("content-length")).longvalue(); } else { size = loadedbytes + long.valueof(con.getheaderfield("content-length")).longvalue(); } // fortschritts-event alle abonnenten senden (downloadprogresslistener l: progresslisteners) { l.setminimum(0); l.setmaximum(size); l.setvalue(loadedbytes); l.setfilename(filename); l.setstatus(downloadprogresslistener.status_running); } // autosave - wenn defaultsavepath gesetzt, baue dateipfad zusammen if (saveto == null && datacontroller.getinstance().getsettingscontroller().getdefaultsavepath() != null && datacontroller.getinstance().getsettingscontroller().getusedefaultsavepath()) { file savetmp = new file(datacontroller.getinstance().getsettingscontroller().getdefaultsavepath(), filename); // prüfe auf gültigkeit, wenn gültig - übernehmen if (savetmp.exists() || savetmp.createnewfile()) { saveto = savetmp; // filename-event auslösen, damit server den "neuen" zielpfad mitgeteilt bekommt (downloadprogresslistener l: progresslisteners) { l.setfilename(saveto.getname()); } } } // wurde der speicherort (immer)noch nicht festgelegt? if (saveto == null) { // speichern-unter dialog öffnen filedialog dia = new filedialog(viewcontroller.getframe(), "save as", filedialog.save); dia.setfile(filename); dia.setvisible(true); //system.out.println("now: " + new date().gettime()); if (dia.getfile() == null) { // user hat abbrechen gedrückt - download abbrechen und aus der liste entfernen if (datacontroller.getinstance().isdebugmode()) system.out.println("download cancelled"); datacontroller.getinstance().removedownload(url); return; } // settings-panel bescheidsagen, dass ein pfad ausgewählt wurde -> defaultsavepath-haken anzeigen datacontroller.getinstance().getsettingscontroller().setlastsavepath(new file(dia.getdirectory())); saveto = new file(dia.getdirectory(), dia.getfile()); if (datacontroller.getinstance().isdebugmode()) system.out.println("saving " + saveto.getabsolutepath()); // neuen dateinamen event-abonnenten propagieren (downloadprogresslistener l: progresslisteners) { l.setfilename(saveto.getname()); } } // erstelle einen neuen thread, der nun unabhängig von der oberfläche im hintergrund den download abarbeitet downloadthread = new thread(new runnable() { @override public void run() { try { // netzwerk-stream öffnen //ins = con.getinputstream(); // dateiausgabe-stream öffnen, rc == httpurlconnection.http_partial => append // outb = new bufferedoutputstream(new fileoutputstream(saveto, rc == httpurlconnection.http_partial)); outb = new fileoutputstream(saveto, rc == httpurlconnection.http_partial); bos = new bufferedoutputstream(outb); bis = new bufferedinputstream(con.getinputstream()); loadedbytes = saveto.length(); byte data [] = new byte[1024]; int count; long bytesread = 0; long lasttime = system.currenttimemillis(); long = 0; int bytespersecond = 0; long timediff = 0; int timeleft = 0; system.out.println("first size loadedbytes "+loadedbytes); // lese-schleife //for (count = ins.read(data,0,1024); count >= 0; count = ins.read(data,0,1024)) while (( count = bis.read(data,0,1024)) > -1 ) { // wenn download pausiert oder abgebrochen -> schleife abbrechen if (stop || paused) break; // daten schreiben, zähler erhöhen bos.write(data,0,count); bytesread += count; loadedbytes += count; = system.currenttimemillis(); timediff = system.currenttimemillis() - lasttime; // mehr als 1 sekunde vergangen if (timediff > 1000l) { // geschwindigkeit und restzeit berechnen bytespersecond = (int)math.round(((double)bytesread / (timediff)) * 1000.0); bytesread = 0; lasttime = now; timeleft = (int)math.round((double)(size - loadedbytes) / bytespersecond); // fortschritts-events auslösen (downloadprogresslistener l: progresslisteners) { l.setvalue(loadedbytes); l.setspeed(bytespersecond); l.settimeestimated(timeleft); } viewcontroller.refreshmainprogress(); } } //date timer = new date(); // ausgabe- und netzwerk-stream beenden system.out.println("geladen: " + loadedbytes); bos.flush(); bos.close(); bis.close(); outb.flush(); outb.close(); ins.close(); (downloadprogresslistener l: progresslisteners) { l.setstatus(downloadprogresslistener.status_checksum_verify); } viewcontroller.refreshmainprogress(); if (!paused) { // wurde abgebrochen? if (stop) { // zieldatei löschen, zähler zurücksetzen saveto.delete(); saveto = null; loadedbytes = 0; stop = false; } urlmd5 = datacontroller.geturlmd5(url.tostring()); filemd5 = datacontroller.getmd5(saveto.getcanonicalpath()); if(filemd5!=null && !filemd5.equals("") && urlmd5!=null && !urlmd5.equals("") && filemd5.equals(urlmd5)) // md5 correct { // finished-event auslösen (downloadprogresslistener l: progresslisteners) { l.setchecksum(""); l.setvalue(size); l.setstatus(downloadprogresslistener.status_finished); } viewcontroller.refreshmainprogress(); setrunning(false); }else { // error-md5 (downloadprogresslistener l: progresslisteners) { l.setchecksum(""); l.seterrormessage("error md5 incorrect: filemd5:'" + filemd5 + "' urlmd5:'" + urlmd5 + "'"); l.setstatus(downloadprogresslistener.status_error); } viewcontroller.refreshmainprogress(); /*loadedbytes = 0; retrycount++; saveto.delete(); thread.sleep(1000); if (retrycount < retrymax) { startdownload(); (downloadprogresslistener l: progresslisteners) { l.setstatus(downloadprogresslistener.status_running); } }else { datacontroller.getinstance().downloadsrunning.remove(url); loadedbytes = 0; retrycount = 0; outb.close(); saveto.delete(); }*/ } } else { // pause-event auslösen (downloadprogresslistener l: progresslisteners) { l.setstatus(downloadprogresslistener.status_paused); } } viewcontroller.refreshmainprogress(); //}catch (interruptedexception e) { // e.printstacktrace(); } catch (sslexception e) { try { loadedbytes = 0; retrycount++; outb.close(); bos.close(); saveto.delete(); if (retrycount < retrymax) { system.out.println("error: " + e.getlocalizedmessage() + "\n--> attempt #" + retrycount + ": retrying file '" + saveto.getname() + "' in 2 seconds."); thread.sleep(2000); // 2s startdownload(); } else { // error-event auslösen (downloadprogresslistener l: progresslisteners) { l.seterrormessage("error retreiving network stream [" + e.getmessage() + "]"); l.setstatus(downloadprogresslistener.status_error); } loadedbytes = 0; retrycount = 0; outb.close(); bos.close(); saveto.delete(); } } catch (exception e1) { e1.printstacktrace(); } } catch (ioexception e) { e.printstacktrace(); // error-event auslösen (downloadprogresslistener l: progresslisteners) { l.seterrormessage("error retreiving network stream [" + e.getmessage() + "]"); l.setstatus(downloadprogresslistener.status_error); } try { loadedbytes = 0; retrycount = 0; // ausgabe- und netzwerk-stream beenden, zieldatei löschen bos.flush(); bos.close(); bis.close(); outb.flush(); outb.close(); ins.close(); saveto.delete(); } catch (ioexception e1) {} } catch (securityexception e) { e.printstacktrace(); loadedbytes = 0; retrycount = 0; // error-event auslösen (downloadprogresslistener l: progresslisteners) { l.seterrormessage("error accessing file '" + saveto.getabsolutepath() + "'"); l.setstatus(downloadprogresslistener.status_error); } } } }); downloadthread.start(); } else { string errmsg = "http error status: " + rc + " " + con.getresponsemessage(); (downloadprogresslistener l: progresslisteners) { l.seterrormessage(errmsg); l.setstatus(downloadprogresslistener.status_error); } saveto.delete(); loadedbytes = 0; retrycount = 0; } } catch (exception e) { e.printstacktrace(); loadedbytes = 0; retrycount = 0; try { // ausgabe- und netzwerk-stream beenden bos.flush(); bos.close(); bis.close(); outb.flush(); outb.close(); ins.close(); } catch (exception e1) {} string errmsg = "unknown error"; if (e instanceof malformedurlexception) { errmsg = "invalid url"; } else if (e instanceof unknownhostexception) { errmsg = "unable resolve hostname '" + e.getmessage() + "'. please check network connection."; } else if (e instanceof ioexception) { errmsg = e.getmessage(); //"error retreiving network stream"; } system.out.println(errmsg); // error-event auslösen (downloadprogresslistener l: progresslisteners) { l.seterrormessage(errmsg); l.setstatus(downloadprogresslistener.status_error); } } }
i not able reproduce error every time , seems machines produce more others. maybe false closed handle or that?
if resumed download , saved file isn't of expected length, if shorter, exist, have unhandled error case. don't know what's right situation wound deleting file , starting again.
and need make adjustments mentioned in comment, if clarity.
Comments
Post a Comment