昨天我在bilibili上看狂神老師的視頻學習Java的多綫程,視頻的内容大致是使用多綫程來同時下載幾張網絡圖片。
視頻鏈接:https://www.bilibili.com/video/BV1V4411p7EF?p=4&vd_source=444398cd8953cf6a041edc235ec9bf3c
我跟著狂神把代碼敲了一邊,運行以後卻報紅了:
教程代碼:
package extendsthread;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* 練習Thread,實現多綫程同步下載
*/
public class PracticeThread extends Thread{
private String url; // 網絡圖片地址
private String name; // 保存的文件名
public PracticeThread(String url, String name){
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url, name);
System.out.println("下載文件:" + name);
}
public static void main(String[] args) {
PracticeThread thread1 = new PracticeThread("https://www.yhdmhy.com/poster_s/20160019.jpg", "灰與幻想的格林姆加爾.jpg");
PracticeThread thread2 = new PracticeThread("https://www.yhdmhy.com/poster_s/20110059.jpg", "日常.jpg");
PracticeThread thread3 = new PracticeThread("https://www.yhdmhy.com/poster_s/20210226.jpg", "漂流少年.jpg");
thread1.start();
thread2.start();
thread3.start();
}
}
/**
* Downloader
*/
class WebDownloader{
/**
* Download method
*/
public void downloader(String address, String name){
try {
FileUtils.copyURLToFile(new URL(address), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO異常,downloader方法出現問題");
}
}
}
測試結果:
java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.yhdmhy.com/poster_s/20110059.jpg
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1894)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
at java.net.URL.openStream(URL.java:1045)
at org.apache.commons.io.file.PathUtils.copy(PathUtils.java:276)
at org.apache.commons.io.FileUtils.copyURLToFile(FileUtils.java:1053)
at extendsthread.WebDownloader.downloader(PracticeThread.java:49)
at extendsthread.PracticeThread.run(PracticeThread.java:24)
java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.yhdmhy.com/poster_s/20210226.jpg
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1894)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
at java.net.URL.openStream(URL.java:1045)
at org.apache.commons.io.file.PathUtils.copy(PathUtils.java:276)
at org.apache.commons.io.FileUtils.copyURLToFile(FileUtils.java:1053)
at extendsthread.WebDownloader.downloader(PracticeThread.java:49)
at extendsthread.PracticeThread.run(PracticeThread.java:24)
java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.yhdmhy.com/poster_s/20160019.jpg
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1894)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
at java.net.URL.openStream(URL.java:1045)
at org.apache.commons.io.file.PathUtils.copy(PathUtils.java:276)
at org.apache.commons.io.FileUtils.copyURLToFile(FileUtils.java:1053)
at extendsthread.WebDownloader.downloader(PracticeThread.java:49)
at extendsthread.PracticeThread.run(PracticeThread.java:24)
IO異常,downloader方法出現問題
下載文件:日常.jpg
IO異常,downloader方法出現問題
下載文件:漂流少年.jpg
IO異常,downloader方法出現問題
下載文件:灰與幻想的格林姆加爾.jpg
我的代碼除了要下載的網絡圖片的URL與教程不同外,沒有其他差別了。後來通過詢問才知道這個報紅跟網絡相關。
報紅原因
有一些網絡資源,它在服務器上做了一些設置:在我們請求圖片的時候,他會判斷請求方是誰。正常我們用瀏覽器打開的話,瀏覽器會發送一些header。比方說,我叫Chrome瀏覽器,我現在要請求你的圖片,那服務器就會允許我把這個圖片打開。但是在代碼裏面,因爲我是直接請求的,我沒有包含一些必要的信息,服務器就會判斷出我不是瀏覽器,可能是一段代碼,出於安全的角度,我的請求會被服務器拒絕。在教程視頻中,狂神老師使用的網站當時并沒有做這方面相關的驗證,所以無論是瀏覽器還是代碼,只要裏面的網絡資源被請求,請求方就會得到理想的反饋。
解決方案
導入HttpURLConnection
import java.net.HttpURLConnection;
把downloader方法裏的FileUtils.copyURLToFile(new URL(address), new File(name));
替換成下面的代碼:
URL url = new URL(address);
HttpURLConnection httpcon = (HttpURLConnection) url.openConnection();
httpcon.addRequestProperty("User-Agent", "Mozilla/4.0");
FileUtils.copyInputStreamToFile(httpcon.getInputStream(), new File(name));
httpcon.addRequestProperty("User-Agent", "Mozilla/4.0");
的意思就是:在發送請求的時候,請求方包含了一個數據包,告訴服務器自己其實是一個瀏覽器。Mozilla就是一個瀏覽器通用的代號,firefox,chrome都是這個代號。
最後成功下載了網絡圖片: