mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-20 14:54:31 +01:00
Added FileDownloader
This commit is contained in:
parent
915c9d6f8f
commit
b249be46c7
BIN
arduino-core/lib/commons-codec-1.7.jar
Normal file
BIN
arduino-core/lib/commons-codec-1.7.jar
Normal file
Binary file not shown.
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
|
||||
*
|
||||
* Arduino is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*/
|
||||
package cc.arduino.packages.contributions;
|
||||
|
||||
import static processing.app.I18n._;
|
||||
import static processing.app.I18n.format;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import cc.arduino.utils.FileHash;
|
||||
import cc.arduino.utils.Progress;
|
||||
import cc.arduino.utils.network.FileDownloader;
|
||||
|
||||
public class DownloadableContributionsDownloader {
|
||||
|
||||
private File stagingFolder;
|
||||
|
||||
public DownloadableContributionsDownloader(File _stagingFolder) {
|
||||
stagingFolder = _stagingFolder;
|
||||
}
|
||||
|
||||
public File download(DownloadableContribution contribution,
|
||||
final Progress progress, final String statusText)
|
||||
throws Exception {
|
||||
URL url = new URL(contribution.getUrl());
|
||||
final File outputFile = new File(stagingFolder, contribution.getArchiveFileName());
|
||||
|
||||
// Ensure the existence of staging folder
|
||||
stagingFolder.mkdirs();
|
||||
|
||||
// Need to download or resume downloading?
|
||||
if (!outputFile.isFile() || (outputFile.length() < contribution.getSize())) {
|
||||
download(url, outputFile, progress, statusText);
|
||||
}
|
||||
|
||||
// Test checksum
|
||||
progress.setStatus(_("Verifying archive integrity..."));
|
||||
onProgress(progress);
|
||||
String checksum = contribution.getChecksum();
|
||||
String algo = checksum.split(":")[0];
|
||||
if (!FileHash.hash(outputFile, algo).equals(checksum))
|
||||
throw new Exception(_("CRC doesn't match. File is corrupted."));
|
||||
|
||||
contribution.setDownloaded(true);
|
||||
contribution.setDownloadedFile(outputFile);
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
public void download(URL url, File tmpFile, final Progress progress,
|
||||
final String statusText) throws Exception {
|
||||
FileDownloader downloader = new FileDownloader(url, tmpFile);
|
||||
downloader.addObserver(new Observer() {
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
FileDownloader me = (FileDownloader) o;
|
||||
String msg = "";
|
||||
if (me.getDownloadSize() != null) {
|
||||
long downloaded = me.getInitialSize() + me.getDownloaded() / 1000;
|
||||
long total = me.getInitialSize() + me.getDownloadSize() / 1000;
|
||||
msg = format(_("Downloaded {0}kb of {1}kb."), downloaded, total);
|
||||
}
|
||||
progress.setStatus(statusText + " " + msg);
|
||||
progress.setProgress(me.getProgress());
|
||||
onProgress(progress);
|
||||
}
|
||||
});
|
||||
downloader.download();
|
||||
if (!downloader.isCompleted())
|
||||
throw new Exception(format(_("Error dowloading {0}"), url),
|
||||
downloader.getError());
|
||||
}
|
||||
|
||||
protected void onProgress(Progress progress) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
}
|
214
arduino-core/src/cc/arduino/utils/network/FileDownloader.java
Normal file
214
arduino-core/src/cc/arduino/utils/network/FileDownloader.java
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* This file is part of Arduino.
|
||||
*
|
||||
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
|
||||
*
|
||||
* Arduino is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* As a special exception, you may use this file as part of a free software
|
||||
* library without restriction. Specifically, if other files instantiate
|
||||
* templates or use macros or inline functions from this file, or you compile
|
||||
* this file and link it with other files to produce an executable, this
|
||||
* file does not by itself cause the resulting executable to be covered by
|
||||
* the GNU General Public License. This exception does not however
|
||||
* invalidate any other reasons why the executable file might be covered by
|
||||
* the GNU General Public License.
|
||||
*/
|
||||
package cc.arduino.utils.network;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.util.Observable;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
public class FileDownloader extends Observable {
|
||||
|
||||
public enum Status {
|
||||
CONNECTING, //
|
||||
CONNECTION_TIMEOUT_ERROR, //
|
||||
DOWNLOADING, //
|
||||
COMPLETE, //
|
||||
CANCELLED, //
|
||||
ERROR, //
|
||||
};
|
||||
|
||||
private Status status;
|
||||
private long initialSize;
|
||||
private Long downloadSize = null;
|
||||
private long downloaded;
|
||||
private URL downloadUrl;
|
||||
|
||||
private File outputFile;
|
||||
private InputStream stream = null;
|
||||
private Exception error;
|
||||
|
||||
public FileDownloader(URL url, File file) {
|
||||
downloadUrl = url;
|
||||
outputFile = file;
|
||||
downloaded = 0;
|
||||
initialSize = 0;
|
||||
}
|
||||
|
||||
public long getInitialSize() {
|
||||
return initialSize;
|
||||
}
|
||||
|
||||
public Long getDownloadSize() {
|
||||
return downloadSize;
|
||||
}
|
||||
|
||||
public void setDownloadSize(Long downloadSize) {
|
||||
this.downloadSize = downloadSize;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public long getDownloaded() {
|
||||
return downloaded;
|
||||
}
|
||||
|
||||
private void setDownloaded(long downloaded) {
|
||||
this.downloaded = downloaded;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public float getProgress() {
|
||||
if (downloadSize == null)
|
||||
return 0;
|
||||
if (downloadSize == 0)
|
||||
return 100;
|
||||
return ((float) downloaded / downloadSize) * 100;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public void download() throws InterruptedException {
|
||||
RandomAccessFile file = null;
|
||||
|
||||
try {
|
||||
// Open file and seek to the end of it
|
||||
file = new RandomAccessFile(outputFile, "rw");
|
||||
initialSize = file.length();
|
||||
file.seek(initialSize);
|
||||
|
||||
setStatus(Status.CONNECTING);
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) downloadUrl
|
||||
.openConnection();
|
||||
|
||||
if (downloadUrl.getUserInfo() != null) {
|
||||
String auth = "Basic "
|
||||
+ new String(new Base64().encode(downloadUrl
|
||||
.getUserInfo().getBytes()));
|
||||
connection.setRequestProperty("Authorization", auth);
|
||||
}
|
||||
|
||||
connection.setRequestProperty("Range", "bytes=" + initialSize + "-");
|
||||
connection.setConnectTimeout(5000);
|
||||
setDownloaded(0);
|
||||
|
||||
// Connect
|
||||
connection.connect();
|
||||
int resp = connection.getResponseCode();
|
||||
if (resp < 200 || resp >= 300)
|
||||
throw new IOException(
|
||||
"Recevied invalid http status code from server: " + resp);
|
||||
|
||||
// Check for valid content length.
|
||||
long len = connection.getContentLength();
|
||||
if (len >= 0)
|
||||
setDownloadSize(len);
|
||||
setStatus(Status.DOWNLOADING);
|
||||
|
||||
synchronized (this) {
|
||||
stream = connection.getInputStream();
|
||||
}
|
||||
byte buffer[] = new byte[10240];
|
||||
while (status == Status.DOWNLOADING) {
|
||||
int read = stream.read(buffer);
|
||||
if (read == -1)
|
||||
break;
|
||||
|
||||
file.write(buffer, 0, read);
|
||||
setDownloaded(getDownloaded() + read);
|
||||
|
||||
if (Thread.interrupted())
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
if (getDownloadSize() != null) {
|
||||
if (getDownloaded() < getDownloadSize())
|
||||
throw new Exception("Incomplete download");
|
||||
}
|
||||
setStatus(Status.COMPLETE);
|
||||
} catch (InterruptedException e) {
|
||||
setStatus(Status.CANCELLED);
|
||||
// lets InterruptedException go up to the caller
|
||||
throw e;
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
setStatus(Status.CONNECTION_TIMEOUT_ERROR);
|
||||
setError(e);
|
||||
|
||||
} catch (Exception e) {
|
||||
setStatus(Status.ERROR);
|
||||
setError(e);
|
||||
|
||||
} finally {
|
||||
if (file != null) {
|
||||
try {
|
||||
file.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setError(Exception e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
public Exception getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return status == Status.COMPLETE;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user