您的位置:首页 > 编程语言 > Java开发

java基础第20天_断点续传、屏广软件

2016-06-22 18:02 477 查看
断点续传

package com.it18zhang.downloader;

public class DownloadInfo {

private String url;
private String local;
private int startPos;//起始位置
private int endPos;//结束位置
public DownloadInfo() {
}
public DownloadInfo(String url, String local, int startPos, int endPos) {
this.url = url;
this.local = local;
this.startPos = startPos;
this.endPos = endPos;
}

public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLocal() {
return local;
}
public void setLocal(String local) {
this.local = local;
}
public int getStartPos() {
return startPos;
}
public void setStartPos(int startPos) {
this.startPos = startPos;
}
public int getEndPos() {
return endPos;
}
public void setEndPos(int endPos) {
this.endPos = endPos;
}

}
package com.it18zhang.downloader;

import java.io.RandomAccessFile;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class DownloadManager {
private String url ;
private String local ;
private int count ;
//文件总长度
private int totalLength ;
private List<DownloadInfo> infos ;
private UI ui ;//ui
/**
* DownloadManager
*/
public DownloadManager(String url, String local, int count,UI ui) {
super();
this.url = url;
this.local = local;
this.count = count;
this.ui = ui ;
//准备下载
prepareDownload();
}

private void prepareDownload() {
infos = new ArrayList<DownloadInfo>();
try {
//1.提取文件大小
URL url0 = new URL(url);
this.totalLength = url0.openConnection().getContentLength();
//1'.设置ui的进度条的最大值.
ui.setProgressbarMax(totalLength);
//2.创建本地文件
RandomAccessFile raf = new RandomAccessFile(local, "rw");
raf.setLength(totalLength);
raf.close();
//3.准备DownloadInfo集合
int block = totalLength / count;
//
DownloadInfo info = null ;
for(int i = 0 ; i < count ; i ++){
info = new DownloadInfo();
info.setUrl(url);
info.setLocal(local);
info.setStartPos(i * block);
if(i == (count - 1)){
info.setEndPos(totalLength - 1 );
}
else{
info.setEndPos((i + 1) * block - 1);
}
//
infos.add(info);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* 开始下载
*/
public void start(){
for(DownloadInfo info : infos){
new DownloadThread(info, ui).start();
}
}
}
package com.it18zhang.downloader;

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;

/**
* 下载线程
*/
public class DownloadThread extends Thread {
private DownloadInfo info ;
private UI ui ;

public DownloadThread(DownloadInfo info,UI ui) {
this.info = info;
this.ui = ui ;
}

public void run(){
try {
URL url = new URL(info.getUrl());
URLConnection conn = url.openConnection();
//设置header的key-value
conn.setRequestProperty("Range", "bytes=" + info.getStartPos() + "-" + info.getEndPos());
//获取流
InputStream is = conn.getInputStream();
//定位本地文件
RandomAccessFile raf = new RandomAccessFile(info.getLocal(), "rw");
raf.seek(info.getStartPos());
byte[] buf = new byte[1024];
int len = 0 ;
while((len = is.read(buf)) != -1){
//
while(ui.isPausing){
try {
Thread.sleep(500);
}
catch (Exception e) {
e.printStackTrace();
}
}
raf.write(buf, 0, len);
//更新进度条
ui.updateProcessBar(len);
}
raf.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
package com.it18zhang.downloader;

public class StartUI {

public static void main(String[] args) {
new UI();
}
}
package com.it18zhang.downloader;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;

public class UI extends JFrame {
//url
private JLabel lbUrl;
private JTextField tfUrl;
//本地地址
private JLabel lbLocal;
private JTextField tfLocal;
//线程数量
private JLabel lbCount;
private JTextField tfCount;
//按钮
private JButton btnStart;
//暂停
private JButton btnPause ;
//进度条
private JProgressBar bar ;
//是否暂停
public boolean isPausing = false ;
public UI(){
ini();
}

private void ini(){
this.setBounds(0, 0, 600, 400);
this.setLayout(null);
//url 标签
lbUrl = new JLabel("url : ");
lbUrl.setBounds(0, 0, 100, 50);
this.add(lbUrl);
tfUrl = new JTextField("http://localhost:8000/jdk-7u25-linux-x86_64.tar.gz");
tfUrl.setBounds(120, 0, 400, 50);
this.add(tfUrl);
//local地址
lbLocal = new JLabel("local : ");
lbLocal.setBounds(0, 60, 100, 50);
this.add(lbLocal);
tfLocal = new JTextField("d:/xx.tar.gz");
tfLocal.setBounds(120, 60, 400, 50);
this.add(tfLocal);
//count地址
lbCount = new JLabel("Count : ");
lbCount.setBounds(0, 120, 100, 50);
this.add(lbCount);
tfCount = new JTextField("3");
tfCount.setBounds(120, 120, 400, 50);
this.add(tfCount);
//下载按钮
btnStart = new JButton("开始");
btnStart.setBounds(10, 180, 100, 50);
this.add(btnStart);
btnStart.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
String url = tfUrl.getText();
String local = tfLocal.getText();
int count = Integer.parseInt(tfCount.getText());
DownloadManager mgr = new DownloadManager(url, local, count, UI.this);
mgr.start();
bar.setVisible(true);
}
});
//暂停
btnPause = new JButton("暂停");
btnPause.setBounds(120, 180, 100, 50);
this.add(btnPause);
btnPause.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
UI.this.isPausing = !UI.this.isPausing ;
btnPause.setText(UI.this.isPausing?"继续":"暂停");
}
});
//进度条
bar = new JProgressBar();
bar.setBounds(5, 240, 550,10);
this.add(bar);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}

public synchronized void updateProcessBar(int len) {
int newValue = bar.getValue() + len ;
bar.setValue(newValue);
if(newValue >= bar.getMaximum()){
JDialog d = new JDialog();
d.setTitle("下载完成!");
d.setVisible(true);
d.setBounds(400, 300, 200, 100);
bar.setValue(0);
bar.setVisible(false);
}
}

public void setProgressbarMax(int length) {
bar.setMaximum(length);
}
}
package com.it18zhang.downloader2;

public class DownloadInfo {

//线程索引编号,主要是对应进度条
private int index ;
private String url;
private String local;
private int startPos;//起始位置
private int endPos;//结束位置
public DownloadInfo() {
}
public DownloadInfo(String url, String local, int startPos, int endPos) {
this.url = url;
this.local = local;
this.startPos = startPos;
this.endPos = endPos;
}

public int getIndex() {
return index;
}

public void setIndex(int index) {
this.index = index;
}

public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLocal() {
return local;
}
public void setLocal(String local) {
this.local = local;
}
public int getStartPos() {
return startPos;
}
public void setStartPos(int startPos) {
this.startPos = startPos;
}
public int getEndPos() {
return endPos;
}
public void setEndPos(int endPos) {
this.endPos = endPos;
}

}
package com.it18zhang.downloader2;

import java.io.RandomAccessFile;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
* 下载管理器
*/
public class DownloadManager {
private String url ;
private String local ;
private int count ;
//文件总长度
private int totalLength ;
private List<DownloadInfo> infos ;
public List<DownloadInfo> getInfos() {
return infos;
}

public void setInfos(List<DownloadInfo> infos) {
this.infos = infos;
}

private UI ui ;//ui
/**
* DownloadManager
*/
public DownloadManager(String url, String local, int count,UI ui) {
super();
this.url = url;
this.local = local;
this.count = count;
this.ui = ui ;
//准备下载
prepareDownload();
}

private void prepareDownload() {
infos = new ArrayList<DownloadInfo>();
try {
//1.提取文件大小
URL url0 = new URL(url);
this.totalLength = url0.openConnection().getContentLength();
//1'.设置ui的进度条的最大值.
//ui.setProgressbarMax(totalLength);
//2.创建本地文件
RandomAccessFile raf = new RandomAccessFile(local, "rw");
raf.setLength(totalLength);
raf.close();
//3.准备DownloadInfo集合
int block = totalLength / count;
//
DownloadInfo info = null ;
for(int i = 0 ; i < count ; i ++){
info = new DownloadInfo();
info.setIndex(i);//索引
info.setUrl(url);//url
info.setLocal(local);//local
info.setStartPos(i * block);//startPos
if(i == (count - 1)){
info.setEndPos(totalLength - 1 );
}
else{
info.setEndPos((i + 1) * block - 1);
}
//
infos.add(info);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* 开始下载
*/
public void start(){
for(DownloadInfo info : infos){
new DownloadThread(info, ui).start();
}
}
}
package com.it18zhang.downloader2;

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;

/**
* 下载线程
*/
public class DownloadThread extends Thread {
private DownloadInfo info ;
private UI ui ;

public DownloadThread(DownloadInfo info,UI ui) {
this.info = info;
this.ui = ui ;
}

public void run(){
try {
URL url = new URL(info.getUrl());
URLConnection conn = url.openConnection();
//设置header的key-value
conn.setRequestProperty("Range", "bytes=" + info.getStartPos() + "-" + info.getEndPos());
//获取流
InputStream is = conn.getInputStream();
//定位本地文件
RandomAccessFile raf = new RandomAccessFile(info.getLocal(), "rw");
raf.seek(info.getStartPos());
byte[] buf = new byte[1024];
int len = 0 ;
while((len = is.read(buf)) != -1){
//
while(ui.isPausing){
try {
Thread.sleep(500);
}
catch (Exception e) {
e.printStackTrace();
}
}
raf.write(buf, 0, len);
//更新进度条
ui.updateProcessBar(len,info.getIndex());
}
raf.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
package com.it18zhang.downloader2;

public class StartUI {

public static void main(String[] args) {
new UI();
}
}
package com.it18zhang.downloader2;

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;

public class UI extends JFrame {
//url
private JLabel lbUrl;
private JTextField tfUrl;
//本地地址
private JLabel lbLocal;
private JTextField tfLocal;
//线程数量
private JLabel lbCount;
private JTextField tfCount;
//按钮
private JButton btnStart;
//暂停
private JButton btnPause ;
//进度条数组
private JProgressBar[] bars ;
//是否暂停
public boolean isPausing = false ;
//已经完成任务的线程数
private int completeCount = 0;
public UI(){
ini();
}
/**
* 初始化
*/
private void ini(){
this.setBounds(0, 0, 600, 400);
this.setLayout(null);
//url 标签
lbUrl = new JLabel("url : ");
lbUrl.setBounds(0, 0, 100, 50);
this.add(lbUrl);
tfUrl = new JTextField("http://localhost:8000/jdk-7u25-linux-x86_64.tar.gz");
tfUrl.setBounds(120, 0, 400, 50);
this.add(tfUrl);
//local地址
lbLocal = new JLabel("local : ");
lbLocal.setBounds(0, 60, 100, 50);
this.add(lbLocal);
tfLocal = new JTextField("d:/xx.tar.gz");
tfLocal.setBounds(120, 60, 400, 50);
this.add(tfLocal);
//count地址
lbCount = new JLabel("Count : ");
lbCount.setBounds(0, 120, 100, 50);
this.add(lbCount);
tfCount = new JTextField("3");
tfCount.setBounds(120, 120, 400, 50);
this.add(tfCount);
//下载按钮
btnStart = new JButton("开始");
btnStart.setBounds(10, 180, 100, 50);
this.add(btnStart);
btnStart.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
String url = tfUrl.getText();
String local = tfLocal.getText();
int count = Integer.parseInt(tfCount.getText());
DownloadManager mgr = new DownloadManager(url, local, count, UI.this);
//动态添加进度条
addBars(mgr.getInfos());
//
mgr.start();
}
});
//暂停
btnPause = new JButton("暂停");
btnPause.setBounds(120, 180, 100, 50);
this.add(btnPause);
btnPause.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
UI.this.isPausing = !UI.this.isPausing ;
btnPause.setText(UI.this.isPausing?"继续":"暂停");
}
});
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}

/**
* 动态添加进度条
*/
protected void addBars(List<DownloadInfo> infos) {
bars = new JProgressBar[infos.size()];
int y = 250 ;
for(int i = 0 ; i < infos.size() ; i ++){
DownloadInfo info = infos.get(i);
bars[i] = new JProgressBar();
bars[i].setMaximum(info.getEndPos() - info.getStartPos() + 1);//设置最大值
bars[i].setBounds(10, y + (i * 25), 400, 20);
this.add(bars[i]);
}
this.repaint();
}

/**
* 更新进度条
* @param indx
*/
public void updateProcessBar(int len, int index) {
int newValue = bars[index].getValue() + len ;
bars[index].setValue(newValue);
if(newValue >= bars[index].getMaximum()){
completeCount ++ ;
if(completeCount >= bars.length){
//处理完成
processFinish();
}
}
}

/**
* 处理完成
*/
private void processFinish() {
for(Component cmp : bars){
this.remove(cmp);
}
this.repaint();
}
}
package com.it18zhang.downloader3;

/**
* 下载信息对象
*/
public class DownloadInfo {

//线程索引编号,主要是对应进度条
private int index ;
private String url;
private String local;
private int startPos;//起始位置
private int endPos;//结束位置
private int amount ;//已经下载的数据量
public DownloadInfo() {
}
public DownloadInfo(String url, String local, int startPos, int endPos) {
this.url = url;
this.local = local;
this.startPos = startPos;
this.endPos = endPos;
}

public int getIndex() {
return index;
}

public void setIndex(int index) {
this.index = index;
}

public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLocal() {
return local;
}
public void setLocal(String local) {
this.local = local;
}
public int getStartPos() {
return startPos;
}
public void setStartPos(int startPos) {
this.startPos = startPos;
}
public int getEndPos() {
return endPos;
}
public void setEndPos(int endPos) {
this.endPos = endPos;
}

public int getAmount() {
return amount;
}

public void setAmount(int amount) {
this.amount = amount;
}
}
package com.it18zhang.downloader3;

import java.io.File;
import java.io.FileInputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
* 下载管理器
*/
public class DownloadManager {
private String url ;
private String local ;
private int count ;
//文件总长度
private int totalLength ;
private List<DownloadInfo> infos ;
public List<DownloadInfo> getInfos() {
return infos;
}

public void setInfos(List<DownloadInfo> infos) {
this.infos = infos;
}

private UI ui ;//ui
/**
* DownloadManager
*/
public DownloadManager(String url, String local, int count,UI ui) {
super();
this.url = url;
this.local = local;
this.count = count;
this.ui = ui ;
//准备下载
prepareDownload();
}

private void prepareDownload() {
infos = new ArrayList<DownloadInfo>();
try {
//0.判断下载文件是否存在
File file = new File(local);
if(file.exists()){
File metaFile = new File(local + ".tmp");
//是否存在
if(metaFile.exists()){
this.infos = readInfosFromFile(metaFile);
}
}
//1.提取文件大小
URL url0 = new URL(url);
this.totalLength = url0.openConnection().getContentLength();
//2.创建本地文件
RandomAccessFile raf = new RandomAccessFile(local, "rw");
raf.setLength(totalLength);
raf.close();
//3.准备DownloadInfo集合
int block = totalLength / count;
//
DownloadInfo info = null ;
for(int i = 0 ; i < count ; i ++){
info = new DownloadInfo();
info.setIndex(i);//索引
info.setUrl(url);//url
info.setLocal(local);//local
info.setStartPos(i * block);//startPos
if(i == (count - 1)){
info.setEndPos(totalLength - 1 );
}
else{
info.setEndPos((i + 1) * block - 1);
}
//
infos.add(info);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
//从元文件提供下载信息
private List<DownloadInfo> readInfosFromFile(File metaFile) {
List<DownloadInfo> infos = new ArrayList<DownloadInfo>();
try {
//Hashtable子类
Properties prop = new Properties();
prop.load(new FileInputStream(metaFile));
String url = prop.getProperty("url");
int count = Integer.parseInt(prop.getProperty("count"));
DownloadInfo info = null ;
for(int i = 0 ; i < count ; i ++){
String value = prop.getProperty("thread." + i);
//arr[0]=startPos arr[1] arr[2]
String[] arr = value.split(";");
info = new DownloadInfo();
info.setIndex(i);
info.setUrl(url);
info.setStartPos(Integer.parseInt(arr[0]));
info.setEndPos(Integer.parseInt(arr[1]));
info.setAmount(Integer.parseInt(arr[2]));
String path = metaFile.getAbsolutePath() ;
path = path.substring(0, path.lastIndexOf("."));
info.setLocal(path);
infos.add(info);
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* 开始下载
*/
public void start(){
for(DownloadInfo info : infos){
new DownloadThread(info, ui).start();
}
}
}

package com.it18zhang.downloader3;

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;

//下载线程
public class DownloadThread extends Thread {
private DownloadInfo info ;
private UI ui ;

public DownloadThread(DownloadInfo info,UI ui) {
this.info = info;
this.ui = ui ;
}

public void run(){
try {
URL url = new URL(info.getUrl());
URLConnection conn = url.openConnection();
//设置header的key-value
conn.setRequestProperty("Range", "bytes=" + info.getStartPos() + "-" + info.getEndPos());
//获取流
InputStream is = conn.getInputStream();
//定位本地文件
RandomAccessFile raf = new RandomAccessFile(info.getLocal(), "rw");
raf.seek(info.getStartPos());
byte[] buf = new byte[1024];
int len = 0 ;
while((len = is.read(buf)) != -1){
//
while(ui.isPausing){
try {
Thread.sleep(500);
}
catch (Exception e) {
e.printStackTrace();
}
}
//1.写入文件
raf.write(buf, 0, len);
//2.更新进度条
ui.updateProcessBar(len,info.getIndex());
//3.更新下载信息
info.setAmount(info.getAmount() + len);
}
raf.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
package com.it18zhang.downloader3;

public class StartUI {

public static void main(String[] args) {
new UI();
}
}
package com.it18zhang.downloader3;

import java.io.FileInputStream;
import java.util.Properties;

public class TestApp {

public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.load(new FileInputStream("d:/conf.properties"));
for(Object key : prop.keySet()){
Object value = prop.get(key);
System.out.println(key + "=" + value);
}
}

}

package com.it18zhang.downloader3;

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;

public class UI extends JFrame {
//url
private JLabel lbUrl;
private JTextField tfUrl;
//本地地址
private JLabel lbLocal;
private JTextField tfLocal;
//线程数量
private JLabel lbCount;
private JTextField tfCount;
//按钮
private JButton btnStart;
//暂停
private JButton btnPause ;
//进度条数组
private JProgressBar[] bars ;
//是否暂停
public boolean isPausing = false ;
//已经完成任务的线程数
private int completeCount = 0;
public UI(){
ini();
}
//初始化
private void ini(){
this.setBounds(0, 0, 600, 400);
this.setLayout(null);
//url 标签
lbUrl = new JLabel("url : ");
lbUrl.setBounds(0, 0, 100, 50);
this.add(lbUrl);
tfUrl = new JTextField("http://localhost:8000/jdk-7u25-linux-x86_64.tar.gz");
tfUrl.setBounds(120, 0, 400, 50);
this.add(tfUrl);
//local地址
lbLocal = new JLabel("local : ");
lbLocal.setBounds(0, 60, 100, 50);
this.add(lbLocal);
tfLocal = new JTextField("d:/xx.tar.gz");
tfLocal.setBounds(120, 60, 400, 50);
this.add(tfLocal);
//count地址
lbCount = new JLabel("Count : ");
lbCount.setBounds(0, 120, 100, 50);
this.add(lbCount);
tfCount = new JTextField("3");
tfCount.setBounds(120, 120, 400, 50);
this.add(tfCount);
//下载按钮
btnStart = new JButton("开始");
btnStart.setBounds(10, 180, 100, 50);
this.add(btnStart);
btnStart.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
String url = tfUrl.getText();
String local = tfLocal.getText();
int count = Integer.parseInt(tfCount.getText());
DownloadManager mgr = new DownloadManager(url, local, count, UI.this);
//动态添加进度条
addBars(mgr.getInfos());
//
mgr.start();
}
});
//暂停
btnPause = new JButton("暂停");
btnPause.setBounds(120, 180, 100, 50);
this.add(btnPause);
btnPause.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
UI.this.isPausing = !UI.this.isPausing ;
btnPause.setText(UI.this.isPausing?"继续":"暂停");
}
});
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}

//动态添加进度条
protected void addBars(List<DownloadInfo> infos) {
bars = new JProgressBar[infos.size()];
int y = 250 ;
for(int i = 0 ; i < infos.size() ; i ++){
DownloadInfo info = infos.get(i);
bars[i] = new JProgressBar();
bars[i].setMaximum(info.getEndPos() - info.getStartPos() + 1);//设置最大值
bars[i].setBounds(10, y + (i * 25), 400, 20);
this.add(bars[i]);
}
this.repaint();
}

public void updateProcessBar(int len, int index) {
int newValue = bars[index].getValue() + len ;
bars[index].setValue(newValue);
if(newValue >= bars[index].getMaximum()){
completeCount ++ ;
if(completeCount >= bars.length){
//处理完成
processFinish();
}
}
}

//处理完成
private void processFinish() {
for(Component cmp : bars){
this.remove(cmp);
}
this.repaint();
}
}

package com.it18zhang.urldemo;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class TestApp {

public static void main(String[] args) throws Exception {
String urlStr = "http://localhost:8000/jdk-7u25-linux-x86_64.tar.gz";
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
String type = conn.getContentType();
int length = conn.getContentLength();
System.out.println(type + " : " + length);
InputStream is = conn.getInputStream();
FileOutputStream fos = new FileOutputStream("d:/jdk.gz");
byte[] buf = new byte[1024];
int len = 0 ;
while((len = is.read(buf)) != -1){
fos.write(buf, 0, len);
}
fos.close();
is.close();
}
}
***********************************************学习内容:java屏广 断点续传功能实现遇到问题:动手能力少跟着老师代码敲了几遍分析建立过程,慢慢理解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java 基础 屏广