857
技術社區[雲棲]
使用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