@RequestMapping("testVideo")public String test() {try {SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd/");//组装本地保存地址StringBuilder filePath = new StringBuilder(StorePathUtil.getStorePath());// \\192.168.20.2\store\stu\upload\video\msyk\2023\08\01\EN123123JD\1filePath.append("upload").append(BaseConstant.SEPERATOR).append("video").append(BaseConstant.SEPERATOR).append("msyk").append(BaseConstant.SEPERATOR).append(DATE_FORMAT.format(new Date())).append(BaseConstant.SEPERATOR).append("asdasda").append(BaseConstant.SEPERATOR).append("1").append(BaseConstant.SEPERATOR);for (int i = 0; i < 3; i++) {//保存文件名称String fileName = "测试"+i+".mp4";SiteInfoBean bean = new SiteInfoBean("http://vjs.zencdn.net/v/oceans.mp4",filePath.toString(),fileName , 5);//启动线程,并回调处理信息SiteFileFetch fileFetch = new SiteFileFetch(bean, result -> System.out.println("downsucc" + result));fileFetch.start();}}catch (Exception e) {e.printStackTrace();}return "succ";}
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.function.Consumer;/*** @author user* @version $$ Revision: 1.0 $$, $$ Date: 2023-08-01 15:45 $$*/
public class SiteFileFetch extends Thread {SiteInfoBean siteInfoBean = null; // 文件信息 Beanlong[] nStartPos; // 开始位置long[] nEndPos; // 结束位置FileSplitterFetch[] fileSplitterFetch; // 子线程对象long nFileLength; // 文件长度boolean bFirst = true; // 是否第一次取文件boolean bStop = false; // 停止标志File tmpFile; // 文件下载的临时信息DataOutputStream output; // 输出到文件的输出流Consumer consumer;public SiteFileFetch(SiteInfoBean bean, Consumer consumer) throws IOException {siteInfoBean = bean;this.consumer = consumer;tmpFile = new File(bean.getSFilePath() + File.separator + bean.getSFileName() + ".info");if (tmpFile.exists()) {bFirst = false;read_nPos();}else {nStartPos = new long[bean.getNSplitter()];nEndPos = new long[bean.getNSplitter()];}}@Overridepublic void run() {// 获得文件长度// 分割文件// 实例 FileSplitterFetch// 启动 FileSplitterFetch 线程// 等待子线程返回try {if (bFirst) {nFileLength = getFileSize();if (nFileLength == -1) {System.err.println("File Length is not known!");}else if (nFileLength == -2) {System.err.println("File is not access!");}else {for (int i = 0; i < nStartPos.length; i++) {nStartPos[i] = (long) (i * (nFileLength / nStartPos.length));}for (int i = 0; i < nEndPos.length - 1; i++) {nEndPos[i] = nStartPos[i + 1];}nEndPos[nEndPos.length - 1] = nFileLength;}//判断文件夹是否存在File file = new File(siteInfoBean.getSFilePath());if (!file.exists()) {file.mkdirs();}}// 启动子线程fileSplitterFetch = new FileSplitterFetch[nStartPos.length];for (int i = 0; i < nStartPos.length; i++) {fileSplitterFetch[i] = new FileSplitterFetch(siteInfoBean.getSSiteURL(),siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(), nStartPos[i],nEndPos[i], i);Utility.log("Thread " + i + " , nStartPos = " + nStartPos[i] + ", nEndPos = " + nEndPos[i]);fileSplitterFetch[i].start();}// fileSplitterFetch[nPos.length - 1] = new FileSplitterFetch(siteInfoBean.getSSiteURL(),// siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(), nPos[nPos.length - 1],// nFileLength, nPos.length - 1);// Utility.log("Thread " + (nPos.length - 1) + ",nStartPos = " + nPos[nPos.length - 1] + ",nEndPos = "// + nFileLength);// fileSplitterFetch[nPos.length - 1].start();// 等待子线程结束//int count = 0;// 是否结束 while 循环boolean breakWhile = false;while (!bStop) {write_nPos();Utility.sleep(500);breakWhile = true;for (int i = 0; i < nStartPos.length; i++) {if (!fileSplitterFetch[i].bDownOver) {breakWhile = false;break;}}if (breakWhile) {break;}//count++;//if(count>4)// siteStop();}System.err.println("文件下载结束!");tmpFile.delete();consumer.accept("下载地址:" + siteInfoBean.getSSiteURL() + ",保存地址:" + siteInfoBean.getSFilePath()+ siteInfoBean.getSFileName());}catch (Exception e) {e.printStackTrace();}finally {}}// 获得文件长度public long getFileSize() {int nFileLength = -1;try {URL url = new URL(siteInfoBean.getSSiteURL());HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();httpConnection.setRequestProperty("User-Agent", "NetFox");int responseCode = httpConnection.getResponseCode();if (responseCode >= 400) {processErrorCode(responseCode);return -2; //-2 represent access is error}String sHeader;for (int i = 1; ; i++) {//DataInputStream in = new DataInputStream(httpConnection.getInputStream ());//Utility.log(in.readLine());sHeader = httpConnection.getHeaderFieldKey(i);if (sHeader != null) {if (sHeader.equals("Content-Length")) {nFileLength = Integer.parseInt(httpConnection.getHeaderField(sHeader));break;}}else {break;}}}catch (Exception e) {e.printStackTrace();}Utility.log(nFileLength);return nFileLength;}// 保存下载信息(文件指针位置)private void write_nPos() {try {output = new DataOutputStream(new FileOutputStream(tmpFile));output.writeInt(nStartPos.length);for (int i = 0; i < nStartPos.length; i++) {// output.writeLong(nPos[i]);output.writeLong(fileSplitterFetch[i].nStartPos);output.writeLong(fileSplitterFetch[i].nEndPos);}output.close();}catch (Exception e) {e.printStackTrace();}}// 读取保存的下载信息(文件指针位置)private void read_nPos() {try {DataInputStream input = new DataInputStream(new FileInputStream(tmpFile));int nCount = input.readInt();nStartPos = new long[nCount];nEndPos = new long[nCount];for (int i = 0; i < nStartPos.length; i++) {nStartPos[i] = input.readLong();nEndPos[i] = input.readLong();}input.close();}catch (Exception e) {e.printStackTrace();}}private void processErrorCode(int nErrorCode) {System.err.println("Error Code : " + nErrorCode);}// 停止文件下载public void siteStop() {bStop = true;for (int i = 0; i < nStartPos.length; i++) {fileSplitterFetch[i].splitterStop();}}
}
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class FileSplitterFetch extends Thread {String sURL; //File URLlong nStartPos; //File Snippet Start Positionlong nEndPos; //File Snippet End Positionint nThreadID; //Thread's IDboolean bDownOver = false; //Downing is overboolean bStop = false; //Stop identicalFileAccessI fileAccessI = null; //File Access interfacepublic FileSplitterFetch(String sURL, String sName, long nStart, long nEnd, int id) throws IOException {this.sURL = sURL;this.nStartPos = nStart;this.nEndPos = nEnd;nThreadID = id;fileAccessI = new FileAccessI(sName, nStartPos);}@Overridepublic void run() {while (nStartPos < nEndPos && !bStop) {try {URL url = new URL(sURL);HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();httpConnection.setRequestProperty("User-Agent", "NetFox");String sProperty = "bytes=" + nStartPos + "-";httpConnection.setRequestProperty("RANGE", sProperty);Utility.log(sProperty);InputStream input = httpConnection.getInputStream();//logResponseHead(httpConnection);byte[] b = new byte[1024];int nRead;while ((nRead = input.read(b, 0, 1024)) > 0 && nStartPos < nEndPos && !bStop) {nStartPos += fileAccessI.write(b, 0, nRead);//if(nThreadID == 1)// Utility.log("nStartPos = " + nStartPos + ", nEndPos = " + nEndPos);}Utility.log("Thread " + nThreadID + " is over!");bDownOver = true;//nPos = fileAccessI.write (b,0,nRead);}catch (Exception e) {e.printStackTrace();}finally {try {fileAccessI.close();}catch (IOException e) {e.printStackTrace();}}}}// 打印回应的头信息public void logResponseHead(HttpURLConnection con) {for (int i = 1; ; i++) {String header = con.getHeaderFieldKey(i);if (header != null) {//responseHeaders.put(header,httpConnection.getHeaderField(header));Utility.log(header + " : " + con.getHeaderField(header));}else {break;}}}public void splitterStop() {bStop = true;}
}
public class SiteInfoBean {private String sSiteURL; //Site's URLprivate String sFilePath; //Saved File's Pathprivate String sFileName; //Saved File's Nameprivate int nSplitter; //Count of Splited Downloading Filepublic SiteInfoBean(){//default value of nSplitter is 5this("","","",5);}public SiteInfoBean(String sURL,String sPath,String sName,int nSpiltter){sSiteURL= sURL;sFilePath = sPath;sFileName = sName;this.nSplitter = nSpiltter;}public String getSSiteURL(){return sSiteURL;}public void setSSiteURL(String value){sSiteURL = value;}public String getSFilePath(){return sFilePath;}public void setSFilePath(String value){sFilePath = value;}public String getSFileName(){return sFileName;}public void setSFileName(String value){sFileName = value;}public int getNSplitter(){return nSplitter;}public void setNSplitter(int nCount){nSplitter = nCount;}
}
import java.io.*;class FileAccessI implements Serializable{RandomAccessFile oSavedFile;long nPos;public FileAccessI() throws IOException {this("",0);}public FileAccessI(String sName,long nPos) throws IOException {oSavedFile = new RandomAccessFile(sName,"rw");this.nPos = nPos;oSavedFile.seek(nPos);}public synchronized int write(byte[] b,int nStart,int nLen){int n = -1;try{oSavedFile.write(b,nStart,nLen);n = nLen;}catch(IOException e){e.printStackTrace ();}return n;}void close() throws IOException {oSavedFile.close();}
}
public class Utility {public Utility() {}public static void sleep(int nSecond) {try {Thread.sleep(nSecond);}catch (Exception e) {e.printStackTrace();}}public static void log(String sMsg) {System.err.println(sMsg);}public static void log(int sMsg) {System.err.println(sMsg);}
}