使用HttpURLConnection下載文件時出現 java.io.FileNotFoundException徹底解決辦法
使用HttpURLConnection下載文件時經常會出現 java.io.FileNotFoundException文件找不到異常,下麵介紹下解決辦法
首先設置tomcat對get數據的編碼:conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />
其次對請求的文件名進行編碼:
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
/**
* 多線程下載
* @author bing
*
*/
public class OmbDownloadOfThreadsUtil {
private String urlPath ; // 資源網絡路徑
private String targetFilePath ; // 所下載文件的保存路徑
private int threadNum ; // 啟用多少條線程進行下載
// 用於下載線程對象集合
private DownloadThread[] downloadThreads ;
// 要下載文件的大小
private int fileSize ;
public OmbDownloadOfThreadsUtil(String urlPath, String targetFilePath,
int threadNum) {
this.urlPath = urlPath;
this.targetFilePath = targetFilePath;
this.threadNum = threadNum;
downloadThreads = new DownloadThread[threadNum] ;
}
public void downloadFile() throws Exception{
URL url = new URL(urlPath) ;
HttpURLConnection conn = (HttpURLConnection) url.openConnection() ;
conn.setConnectTimeout(4*1000) ;
conn.setRequestMethod("GET") ;
conn.setRequestProperty(
"Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, " +
"application/x-shockwave-flash, application/xaml+xml, " +
"application/vnd.ms-xpsdocument, application/x-ms-xbap, " +
"application/x-ms-application, application/vnd.ms-excel, " +
"application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
//設置瀏覽器類型和版本、操作係統,使用語言等信息
conn.setRequestProperty(
"User-Agent",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; Trident/4.0; " +
".NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; " +
".NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
//設置為長連接
conn.setRequestProperty("Connection", "Keep-Alive");
//得到要下載文件的大小
fileSize = conn.getContentLength() ;
System.out.println("fileSize:"+fileSize);
//斷開連接
conn.disconnect() ;
//計算每條線程需要下載的大小
int preThreadDownloadSize = fileSize/threadNum+1 ;
System.out.println("preThreadDownloadSize:"+preThreadDownloadSize);
RandomAccessFile file = new RandomAccessFile(targetFilePath, "rw") ;
file.setLength(fileSize) ;
file.close() ;
for (int i = 0; i < threadNum; i++) {
// 計算每條線程下載的起始位置
int startPos = i*preThreadDownloadSize+1 ;
RandomAccessFile currentPart = new RandomAccessFile(targetFilePath, "rw") ;
currentPart.seek(startPos) ;
downloadThreads[i] = new DownloadThread(startPos,preThreadDownloadSize,currentPart) ;
new Thread(downloadThreads[i]).start() ;
}
}
/**
* 獲取下載的完成百分比
* @return 完成的百分比
*/
public double getCompleteRate() {
// 統計多條線程已經下載的總大小
int sumSize = 0;
for (int i = 0; i < threadNum; i++) {
sumSize += downloadThreads[i].hasReadLength;
}
// 返回已經完成的百分比
return sumSize * 1.0 / fileSize;
}
/**
* 用於下載的線程
* @author bing
*
*/
private final class DownloadThread implements Runnable{
private int startPos ;
private int preThreadDownloadSize ;
private RandomAccessFile currentPart ;
//已下載長度
private int hasReadLength ;
public DownloadThread(int startPos, int preThreadDownloadSize,
RandomAccessFile currentPart) {
this.startPos = startPos;
this.preThreadDownloadSize = preThreadDownloadSize;
this.currentPart = currentPart;
}
@Override
public void run() {
InputStream inputStream = null ;
try{
URL url = new URL(urlPath) ;
HttpURLConnection conn = (HttpURLConnection) url.openConnection() ;
conn.setConnectTimeout(4*1000) ;
conn.setRequestMethod("GET") ;
conn.setRequestProperty(
"Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, " +
"application/x-shockwave-flash, application/xaml+xml, " +
"application/vnd.ms-xpsdocument, application/x-ms-xbap, " +
"application/x-ms-application, application/vnd.ms-excel, " +
"application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
inputStream = conn.getInputStream() ;
inputStream.skip(startPos) ;//定位到開始位置
byte[] buffer = new byte[1024] ;
int temp = 0 ;
while(hasReadLength<preThreadDownloadSize
&&(temp=inputStream.read(buffer))!=-1){
currentPart.write(buffer,0,temp) ;
hasReadLength += temp ;
}
}catch(Exception e){
e.printStackTrace() ;
}finally{
try {
currentPart.close() ;
} catch (Exception e) {
e.printStackTrace();
}
try {
inputStream.close() ;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
String songName = "許嵩 - 半城煙沙.mp3" ;
songName = URLEncoder.encode(songName,"UTF-8") ;
String urlPath = "https://172.16.2.50:8080/mp3/"+songName ;
String targetDir = "E:"+File.separator+songName ;
OmbDownloadOfThreadsUtil odtu = new OmbDownloadOfThreadsUtil(urlPath,targetDir, 6) ;
odtu.downloadFile() ;
}
}
經過以上三步基本上問題已經解決,但如果的文件名含有空格的話還需一步:
URLs是不能包含空格的。URL encoding一般會使用“+”號去替換空格,但後台服務器(我的是Tomcat6.0)又不能把“+”還原為空格,所以導致文件找不到,解決辦法:隻需把“+”替換為“%20”
public static void main(String[] args) throws Exception {
String songName = "許嵩 - 半城煙沙.mp3" ;
songName = URLEncoder.encode(songName,"UTF-8").replace("+", "%20") ;
String urlPath = "https://172.16.2.50:8080/mp3/"+songName ;
String targetDir = "E:"+File.separator+songName ;
OmbDownloadOfThreadsUtil odtu = new OmbDownloadOfThreadsUtil(urlPath,targetDir, 6) ;
odtu.downloadFile() ;
}
最後更新:2017-04-03 22:15:39