[英]While accessing http in wildfly9, a blank download file is getting downloaded
[英]HTTP-Download - sometimes file is not downloaded complete without error
我正在嘗試開發一個小型Java下載器。 但有時,我無法確定何時下載一次會丟失百分之幾。 一個下載損壞后,以后的每個下載也將損壞。 我不知道我的問題在哪里,並嘗試了一些不同的輸出緩沖區,但沒有成功。 這是下載線程的來源:
private void startDownload() {
try {
ins = null;
outb=null;
setRunning(true);
// Erstelle HttpURLConnection Objekt zur Anfrage an 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 TO 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 an alle Abonnenten senden
for (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
for (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 to " + saveTo.getAbsolutePath());
// Neuen Dateinamen an Event-Abonnenten propagieren
for (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 now = 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;
now = 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
for (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();
for (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 is correct
{
// Finished-Event auslösen
for (DownloadProgressListener l: progressListeners) {
l.setChecksum("");
l.setValue(size);
l.setStatus(DownloadProgressListener.STATUS_FINISHED);
}
ViewController.refreshMainProgress();
setRunning(false);
}else
{ // Error-MD5
for (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();
for (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
for (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
for (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
for (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
for (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();
for (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 to resolve hostname '" + e.getMessage() + "'. Please check your network connection.";
} else if (e instanceof IOException) {
errMsg = e.getMessage(); //"Error retreiving network stream";
}
System.out.println(errMsg);
// Error-Event auslösen
for (DownloadProgressListener l: progressListeners) {
l.setErrorMessage(errMsg);
l.setStatus(DownloadProgressListener.STATUS_ERROR);
}
}
}
我無法每次都重現該錯誤,似乎有些機器會像其他機器那樣更頻繁地產生該錯誤。 也許是帶有錯誤的閉合手柄或類似的東西?
如果這是恢復的下載,並且保存的文件不是預期的長度,特別是如果較短,但確實存在,則表示您有未處理的錯誤情況。 我不知道哪種方式適合您的情況,但是我很想刪除該文件然后重新開始。
如果只是為了清楚起見,您需要進行我的評論中提到的所有調整。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.