Ada sebuah file online (seperti http://www.example.com/information.asp
) aku harus ambil dan simpan ke direktori. Saya tahu ada beberapa metode untuk meraih dan membaca file online (Url) baris-demi-baris, tapi apakah ada cara untuk hanya men-download dan menyimpan file menggunakan Java?
Memberikan Jawa NIO mencoba:
URL website = new URL("http://www.website.com/information.asp");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("information.html");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
Menggunakan transferFrom()
adalah potensial jauh lebih efisien daripada loop sederhana yang membaca dari sumber channel dan menulis ke saluran ini. Banyak sistem operasi yang dapat mentransfer byte langsung dari sumbernya ke saluran filesystem cache tanpa benar-benar menyalin mereka.
Cek lebih lanjut tentang hal itu di sini.
Catatan: ketiga parameter di transferFrom adalah jumlah maksimal byte untuk transfer. Integer.MAX_VALUE
akan transfer paling banyak 2^31 byte, Panjang.MAX_VALUE
akan memungkinkan paling banyak 2^63 byte (lebih besar dari setiap file yang ada).
public void saveUrl(final String filename, final String urlString)
throws MalformedURLException, IOException {
BufferedInputStream in = null;
FileOutputStream fout = null;
try {
in = new BufferedInputStream(new URL(urlString).openStream());
fout = new FileOutputStream(filename);
final byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1) {
fout.write(data, 0, count);
}
} finally {
if (in != null) {
in.close();
}
if (fout != null) {
fout.close();
}
}
}
Anda'akan perlu untuk menangani pengecualian, mungkin eksternal untuk metode ini.
Men-download sebuah file yang mengharuskan anda untuk membaca ini, entah cara anda akan memiliki untuk pergi melalui file dalam beberapa cara. Bukannya baris demi baris, anda hanya dapat membacanya dengan byte dari aliran:
BufferedInputStream in = new BufferedInputStream(new URL("http://www.website.com/information.asp").openStream())
byte data[] = new byte[1024];
int count;
while((count = in.read(data,0,1024)) != -1)
{
out.write(data, 0, count);
}
It's sebuah pertanyaan lama tapi di sini adalah ringkas, mudah dibaca, JDK-satunya solusi dengan benar tertutup sumber:
public static void download(String url, String fileName) throws Exception {
try (InputStream in = URI.create(url).toURL().openStream()) {
Files.copy(in, Paths.get(fileName));
}
}
Dua baris kode dan tidak ada ketergantungan.
Ketika menggunakan Jawa 7+
menggunakan metode berikut untuk men-download file dari Internet dan menyimpannya ke beberapa direktori:
private static Path download(String sourceURL, String targetDirectory) throws IOException
{
URL url = new URL(sourceURL);
String fileName = sourceURL.substring(sourceURL.lastIndexOf('/') + 1, sourceURL.length());
Path targetPath = new File(targetDirectory + File.separator + fileName).toPath();
Files.copy(url.openStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
return targetPath;
}
Dokumentasi di sini.
Jawaban ini hampir persis seperti yang dipilih menjawab tapi dengan dua tambahan: it's metode dan menutup keluar FileOutputStream objek:
public static void downloadFileFromURL(String urlString, File destination) {
try {
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
import java.io.*;
import java.net.*;
public class filedown {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "\t" + numWritten);
}
catch (Exception exception) {
exception.printStackTrace();
}
finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
catch (IOException ioe) {
}
}
}
public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, (new URL(address)).getFile());
}
else {
System.err.println("Could not figure out local file name for "+address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}
}
Secara pribadi, saya've ditemukan Apache's HttpClient untuk lebih dari mampu dari segala sesuatu yang saya've diperlukan untuk melakukan dengan hal ini. Di sini adalah sebuah tutorial tentang menggunakan HttpClient
Ini adalah satu lagi java7 varian berdasarkan Brian Risiko's jawaban dengan penggunaan mencoba-dengan pernyataan:
public static void downloadFileFromURL(String urlString, File destination) throws Throwable {
URL website = new URL(urlString);
try(
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
){
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
}
Ada banyak yang elegan dan efisien jawaban di sini. Tapi keringkasan dapat membuat kita kehilangan beberapa informasi yang berguna. Secara khusus, salah satu sering tidak ingin untuk mempertimbangkan kesalahan koneksi Pengecualian, dan satu mungkin ingin mengobati berbeda beberapa jenis jaringan yang berhubungan dengan kesalahan - misalnya, untuk memutuskan apakah kita harus coba lagi download.
Berikut ini's sebuah metode yang tidak melempar Pengecualian untuk kesalahan jaringan (hanya untuk yang benar-benar luar biasa masalah, sebagai salah bentuk url atau masalah menulis ke file)
/**
* Downloads from a (http/https) URL and saves to a file.
* Does not consider a connection error an Exception. Instead it returns:
*
* 0=ok
* 1=connection interrupted, timeout (but something was read)
* 2=not found (FileNotFoundException) (404)
* 3=server error (500...)
* 4=could not connect: connection timeout (no internet?) java.net.SocketTimeoutException
* 5=could not connect: (server down?) java.net.ConnectException
* 6=could not resolve host (bad host, or no internet - no dns)
*
* @param file File to write. Parent directory will be created if necessary
* @param url http/https url to connect
* @param secsConnectTimeout Seconds to wait for connection establishment
* @param secsReadTimeout Read timeout in seconds - trasmission will abort if it freezes more than this
* @return See above
* @throws IOException Only if URL is malformed or if could not create the file
*/
public static int saveUrl(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout) throws IOException {
Files.createDirectories(file.getParent()); // make sure parent dir exists , this can throw exception
URLConnection conn = url.openConnection(); // can throw exception if bad url
if( secsConnectTimeout > 0 ) conn.setConnectTimeout(secsConnectTimeout * 1000);
if( secsReadTimeout > 0 ) conn.setReadTimeout(secsReadTimeout * 1000);
int ret = 0;
boolean somethingRead = false;
try (InputStream is = conn.getInputStream()) {
try (BufferedInputStream in = new BufferedInputStream(is); OutputStream fout = Files
.newOutputStream(file)) {
final byte data[] = new byte[8192];
int count;
while((count = in.read(data)) > 0) {
somethingRead = true;
fout.write(data, 0, count);
}
}
} catch(java.io.IOException e) {
int httpcode = 999;
try {
httpcode = ((HttpURLConnection) conn).getResponseCode();
} catch(Exception ee) {}
if( somethingRead && e instanceof java.net.SocketTimeoutException ) ret = 1;
else if( e instanceof FileNotFoundException && httpcode >= 400 && httpcode < 500 ) ret = 2;
else if( httpcode >= 400 && httpcode < 600 ) ret = 3;
else if( e instanceof java.net.SocketTimeoutException ) ret = 4;
else if( e instanceof java.net.ConnectException ) ret = 5;
else if( e instanceof java.net.UnknownHostException ) ret = 6;
else throw e;
}
return ret;
}
Ada metode U. fetch(url) di underscore-jawa perpustakaan.
pom.xml:
<groupId>com.github.javadev</groupId>
<artifactId>underscore</artifactId>
<version>1.45</version>
Contoh kode:
import com.github.underscore.lodash.U;
public class Download {
public static void main(String ... args) {
String text = U.fetch("https://stackoverflow.com/questions"
+ "/921262/how-to-download-and-save-a-file-from-internet-using-java").text();
}
}
Untuk meringkas (dan entah bagaimana polandia dan update) jawaban sebelumnya. Berikut tiga metode praktis yang setara. (Saya menambahkan eksplisit timeout karena saya pikir mereka adalah suatu keharusan, tak seorang pun ingin download untuk membekukan selamanya ketika koneksi terputus.)
public static void saveUrl1(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout))
throws MalformedURLException, IOException {
// Files.createDirectories(file.getParent()); // optional, make sure parent dir exists
try (BufferedInputStream in = new BufferedInputStream(
streamFromUrl(url, secsConnectTimeout,secsReadTimeout) );
OutputStream fout = Files.newOutputStream(file)) {
final byte data[] = new byte[8192];
int count;
while((count = in.read(data)) > 0)
fout.write(data, 0, count);
}
}
public static void saveUrl2(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout))
throws MalformedURLException, IOException {
// Files.createDirectories(file.getParent()); // optional, make sure parent dir exists
try (ReadableByteChannel rbc = Channels.newChannel(
streamFromUrl(url, secsConnectTimeout,secsReadTimeout)
);
FileChannel channel = FileChannel.open(file,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE)
) {
channel.transferFrom(rbc, 0, Long.MAX_VALUE);
}
}
public static void saveUrl3(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout))
throws MalformedURLException, IOException {
// Files.createDirectories(file.getParent()); // optional, make sure parent dir exists
try (InputStream in = streamFromUrl(url, secsConnectTimeout,secsReadTimeout) ) {
Files.copy(in, file, StandardCopyOption.REPLACE_EXISTING);
}
}
public static InputStream streamFromUrl(URL url,int secsConnectTimeout,int secsReadTimeout) throws IOException {
URLConnection conn = url.openConnection();
if(secsConnectTimeout>0) conn.setConnectTimeout(secsConnectTimeout*1000);
if(secsReadTimeout>0) conn.setReadTimeout(secsReadTimeout*1000);
return conn.getInputStream();
}
Saya don't menemukan perbedaan yang signifikan, semua tampak baik-baik kepada saya. Mereka aman dan efisien. (Perbedaan dalam kecepatan tampaknya tidak relevan - aku menulis 180Mb dari server lokal ke SSD disk pada saat yang berfluktuasi di sekitar 1,2-1,5 segs). Mereka don't membutuhkan perpustakaan eksternal. Semua bekerja dengan ukuran sewenang-wenang dan (pengalaman saya) HTTP pengalihan.
Selain itu, semua membuang FileNotFoundException
jika sumber daya yang tidak ditemukan (error 404, biasanya), dan jawa.net.UnknownHostException
jika resolusi DNS gagal; lain IOException sesuai dengan kesalahan selama transmisi.
(Ditandai sebagai komunitas wiki, merasa bebas untuk menambahkan info atau koreksi)
It's mungkin untuk men-download file dengan dengan Apache's HttpComponents
bukan Commons IO
. Kode ini memungkinkan anda untuk men-download file di Jawa menurut URL-nya dan menyimpannya di tujuan tertentu.
public static boolean saveFile(URL fileURL, String fileSavePath) {
boolean isSucceed = true;
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(fileURL.toString());
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
httpGet.addHeader("Referer", "https://www.google.com");
try {
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity fileEntity = httpResponse.getEntity();
if (fileEntity != null) {
FileUtils.copyInputStreamToFile(fileEntity.getContent(), new File(fileSavePath));
}
} catch (IOException e) {
isSucceed = false;
}
httpGet.releaseConnection();
return isSucceed;
}
Berbeda dengan satu baris kode:
FileUtils.copyURLToFile(fileURL, new File(fileSavePath),
URLS_FETCH_TIMEOUT, URLS_FETCH_TIMEOUT);
kode ini akan memberikan anda kontrol lebih besar atas proses dan membiarkan anda menentukan tidak hanya waktu menyendiri tapi User-Agent
dan Referer
nilai-nilai, yang sangat penting untuk banyak situs web.
Ada masalah dengan penggunaan sederhana dari:
org.apache.commons.io.FileUtils.copyURLToFile(URL, File)
jika anda perlu untuk men-download dan menyimpan file yang sangat besar, atau secara umum jika anda membutuhkan pengulangan otomatis dalam kasus koneksi dijatuhkan.
Apa yang saya sarankan dalam kasus tersebut adalah Apache HttpClient bersama dengan org.apache.commons.io.FileUtils. Misalnya:
GetMethod method = new GetMethod(resource_url);
try {
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
logger.error("Get method failed: " + method.getStatusLine());
}
org.apache.commons.io.FileUtils.copyInputStreamToFile(
method.getResponseBodyAsStream(), new File(resource_file));
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
method.releaseConnection();
}
Di bawah ini adalah contoh kode untuk men-download film dari internet dengan kode java:
URL url = new
URL("http://103.66.178.220/ftp/HDD2/Hindi%20Movies/2018/Hichki%202018.mkv");
BufferedInputStream bufferedInputStream = new BufferedInputStream(url.openStream());
FileOutputStream stream = new FileOutputStream("/home/sachin/Desktop/test.mkv");
int count=0;
byte[] b1 = new byte[100];
while((count = bufferedInputStream.read(b1)) != -1) {
System.out.println("b1:"+b1+">>"+count+ ">> KB downloaded:"+new File("/home/sachin/Desktop/test.mkv").length()/1024);
stream.write(b1, 0, count);
}
Jika anda berada di belakang proxy, anda dapat mengatur proxy di java program seperti di bawah ini:
Properties systemSettings = System.getProperties();
systemSettings.put("proxySet", "true");
systemSettings.put("https.proxyHost", "https proxy of your org");
systemSettings.put("https.proxyPort", "8080");
Jika anda tidak berada di belakang proxy, don't memiliki garis di atas dalam kode anda. Bekerja penuh kode untuk men-download file ketika anda berada di belakang proxy.
public static void main(String[] args) throws IOException {
String url="https://raw.githubusercontent.com/bpjoshi/fxservice/master/src/test/java/com/bpjoshi/fxservice/api/TradeControllerTest.java";
OutputStream outStream=null;
URLConnection connection=null;
InputStream is=null;
File targetFile=null;
URL server=null;
//Setting up proxies
Properties systemSettings = System.getProperties();
systemSettings.put("proxySet", "true");
systemSettings.put("https.proxyHost", "https proxy of my organisation");
systemSettings.put("https.proxyPort", "8080");
//The same way we could also set proxy for http
System.setProperty("java.net.useSystemProxies", "true");
//code to fetch file
try {
server=new URL(url);
connection = server.openConnection();
is = connection.getInputStream();
byte[] buffer = new byte[is.available()];
is.read(buffer);
targetFile = new File("src/main/resources/targetFile.java");
outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
} catch (MalformedURLException e) {
System.out.println("THE URL IS NOT CORRECT ");
e.printStackTrace();
} catch (IOException e) {
System.out.println("Io exception");
e.printStackTrace();
}
finally{
if(outStream!=null) outStream.close();
}
}
public class DownloadManager {
static String urls = "[WEBSITE NAME]";
public static void main(String[] args) throws IOException{
URL url = verify(urls);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream in = null;
String filename = url.getFile();
filename = filename.substring(filename.lastIndexOf('/') + 1);
FileOutputStream out = new FileOutputStream("C:\\Java2_programiranje/Network/DownloadTest1/Project/Output" + File.separator + filename);
in = connection.getInputStream();
int read = -1;
byte[] buffer = new byte[4096];
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
System.out.println("[SYSTEM/INFO]: Downloading file...");
}
in.close();
out.close();
System.out.println("[SYSTEM/INFO]: File Downloaded!");
}
private static URL verify(String url){
if(!url.toLowerCase().startsWith("http://")) {
return null;
}
URL verifyUrl = null;
try{
verifyUrl = new URL(url);
}catch(Exception e){
e.printStackTrace();
}
return verifyUrl;
}
}
Anda dapat melakukan ini dalam 1 baris menggunakan netloader untuk Java:
new NetFile(new File("my/zips/1.zip"), "https://example.com/example.zip", -1).load(); //returns true if succeed, otherwise false.