精华内容
下载资源
问答
  • 2021-11-30 16:53:15
    import java.io.*;
    import java.net.Socket;
    
    /*
        客户端:数据来自于文本文件,接收服务器反馈
     */
    public class ClientDemo {
        public static void main(String[] args) throws IOException {
            //创建客户端Socket对象
            Socket s = new Socket("192.168.1.66",10000);
    
            //封装文本文件的数据
            BufferedReader br = new BufferedReader(new FileReader("myNet\\InetAddressDemo.java"));
            //封装输出流写数据
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
    
            String line;
            while ((line=br.readLine())!=null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
    
            s.shutdownOutput();
    
            //接收反馈
            BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String data = brClient.readLine(); //等待读取数据
            System.out.println("服务器的反馈:" + data);
    
            //释放资源
            br.close();
            s.close();
        }
    }
    
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /*
        服务器:接收到的数据写入文本文件,给出反馈,代码用线程进行封装,为每一个客户端开启一个线程
     */
    public class ServerDemo {
        public static void main(String[] args) throws IOException {
            //创建服务器Socket对象
            ServerSocket ss = new ServerSocket(10000);
    
            while (true) {
                //监听客户端连接,返回一个对应的Socket对象
                Socket s = ss.accept();
                //为每一个客户端开启一个线程
                new Thread(new ServerThread(s)).start();
            }
    
    //        ss.close();
        }
    }
    
    
    
    import java.io.*;
    import java.net.Socket;
    
    public class ServerThread implements Runnable {
        private Socket s;
    
        public ServerThread(Socket s) {
            this.s = s;
        }
    
        @Override
        public void run() {
            try {
                //接收数据写到文本文件
                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
    //            BufferedWriter bw = new BufferedWriter(new FileWriter("myNet\\Copy.java"));
                //解决名称冲突问题
                int count = 0;
                File file = new File("myNet\\Copy["+count+"].java");
                while (file.exists()) {
                    count++;
                    file = new File("myNet\\Copy["+count+"].java");
                }
                BufferedWriter bw = new BufferedWriter(new FileWriter(file));
    
                String line;
                while ((line=br.readLine())!=null) {
                    bw.write(line);
                    bw.newLine();
                    bw.flush();
                }
    
                //给出反馈
                BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                bwServer.write("文件上传成功");
                bwServer.newLine();
                bwServer.flush();
    
                //释放资源
                s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    更多相关内容
  • 利用java技术实现多线程文件传输
  • Linux系统下基于Tcp的多线程大文件上传实现.pdf
  • 多线程网络传输大都没有实现大于2G文件,在前人基础上改写的真正的多线程网络传输,不受文件大小的限制!先上传大文件上传的完整代码,有需要文件超过2G的下载,请留言!
  • 主要为大家详细介绍了java多线程实现文件下载,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • qt实现的服务端,可以同时接收个客户端的连接,同时接收个客户端的文件传输任务。
  • 多线程下载文件(支持暂停、取消、断点续传) 多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将...
  • C语言实现 多线程文件传输

    热门讨论 2014-06-11 17:05:32
    本人在工作用的到c语言进程多线程工作,和多线程实现文件传输的功能,就网上寻找一份,供大家参考
  • 本文实例讲述了Python实现模拟分割大文件多线程处理的方法。分享给大家供大家参考,具体如下: #!/usr/bin/env python #--*-- coding:utf-8 --*-- from random import randint from time import ctime from time ...
  • JAVA 实现多线程下载大文件

    千次阅读 2021-12-28 15:22:09
    JAVA 实现多线程下载大文件 开发中遇到一个问题,下载大文件到本地,导致等待时间过长,然后就寻找一个可以多线程下载的办法,受下载软件启发,想到多线程下载, 原理,首先查到这个文件的大小,然后根据线程数量...

    JAVA 实现多线程下载大文件

    开发中遇到一个问题,下载大文件到本地,导致等待时间过长,然后就寻找一个可以多线程下载的办法,受下载软件启发,想到多线程下载,
    原理,首先查到这个文件的大小,然后根据线程数量去分配每个线程下载多大的片段,然后将每个线程的组合到一起,就是最终的下载文件。如图

    在这里插入图片描述

    然后就是代码时间, 必不可少的控制层

        @Override
        @ApiOperation(value = "多线程获取大文件", httpMethod = "POST")
        @BodyValidate
        public Result getBigFile(@RequestBody CommonFileRequest commonFileRequest, HttpServletResponse response) {
            return commonFileService.getBigFile(commonFileRequest,response);
        }
    

    然后是业务层

     /**
         * .
         * @Description: 作用:   多线程获取大文件
         * @Author: LXT
         * @Date: 2021/12/27 9:18
         * @param request 入参
         * @return Result
         */
        public Result getBigFile(CommonFileRequest request, HttpServletResponse response) {
            logger.info("多线程获取大文件," + JSON.toJSONString(request));
             long start = System.currentTimeMillis();
            //超大  6G
            //String path = "???";
            // 1.3G
            //String path = "???";
            //正常大小
            String path = "???";
    
            try {
                ServletOutputStream out = null;
    
                String s = BigFileDownload.BigFileTestUtil(accessKey, secretKey, endpoint, bucketName, path);
                File file = new File(s);
                InputStream fis = new BufferedInputStream(new FileInputStream(file));
    
                response.reset();
                // 设置response的Header
                response.addHeader("Content-Length", "" + file.length());
                response.setContentType("application/octet-stream;charset=UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + UUID.randomUUID().toString().replace("-", "") + ".zip");
    
                out = response.getOutputStream();
                //读取文件流
                int len = 0;
                byte[] buffer = new byte[1024 * 10];
                while ((len = fis.read(buffer)) != -1){
                    out.write(buffer,0,len);
                }
                out.flush();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            logger.info("获取大文件耗时 {}", BusinessStringUtils.formatTime(System.currentTimeMillis() - start));
    
            return null;
        }
    

    解析 首先 记录一下请求的日志 然后是拿到对应的存储位置
    然后去平台获取文件 BigFileDownload.BigFileTestUtil 这个方法
    返回的缓存在服务器 或者本地的一个位置 然后将其返回给移动端
    后边这些就不说了 都是正常的反流代码 这里着重说明 多线程分片下载

    
    /**
     * .
     *
     * @ClassName: BigFileDownload
     * @Description:
     * @Author: LXT
     * @Date: 2021/12/27 13:01
     */
    public class BigFileDownload {
    
        //创建一个计数器锁。初始值为线程数量,每执行结束一个线程后计数器减去1 ,当计数器为0的时候await等待的线程会被唤醒继续执行。
        public static CountDownLatch latch = new CountDownLatch(100);
    
    
        public static String BigFileTestUtil(String accessKey, String secretKey, String endpoint, String bucketName, String downloadFilePath) {
            RandomAccessFile file = null;
            String filename = "D:\\222ddddd2.zip";
            File fileDownService = new File(filename);
            if (!fileDownService.exists()) {
                try {
                    fileDownService.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println("文件已创建");
            } else {
                System.out.println("文件已存在");
            }
            try {
                AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
                ClientConfiguration clientConfig = new ClientConfiguration();
                clientConfig.setProtocol(Protocol.HTTP);
                AmazonS3 s3Client = new AmazonS3Client(credentials, clientConfig);
                s3Client.setEndpoint(endpoint);
                //获取对象大小
                AmazonS3 instance = AmazonS3Builder.getInstance(endpoint, accessKey, secretKey);
                S3Object object = instance.getObject(bucketName, downloadFilePath);
                S3ObjectInputStream in3 = object.getObjectContent();
                ObjectMetadata metadata = object.getObjectMetadata();
                long filesize = metadata.getInstanceLength();
                System.out.println("文件大小:" + filesize);
    
                ExecutorService service = Executors.newFixedThreadPool(100);
                long length = filesize;
                long packageLength = length / 100;
                long leftLength = length % 100;
                long pos = 0;
                long end = packageLength;
                file = new RandomAccessFile(filename, "rw");
                //计算每个线程请求文件的开始和结束位置
                for (int i = 0; i < 100; i++) {
                    if (leftLength > 0) {
                        packageLength++;
                        leftLength--;
                    }
                    System.out.println("pos: " + pos + "  endpos: " + packageLength);
                    service.execute(new BigFileDownloadRunnable(pos, packageLength, file, endpoint, accessKey, secretKey, bucketName, downloadFilePath));
                    pos = packageLength;
                    packageLength = packageLength + end;
                }
                //等待其他线程结束后继续向下执行
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                //关闭线程池
                service.shutdown();
            } catch (AmazonServiceException | FileNotFoundException e) {
                // 服务端错误
                e.printStackTrace();
            } finally {
                if (file != null) {
                    try {
                        file.close();
                    } catch (Exception e) {
    
                    }
                }
            }
            return filename;
    
        }
    
    }
    

    其实也比较好理解 首先创建一个线程 用来分片下载
    然后是主代码
    方法入参 分别是 对象平台的一些参数 只有随后一个是存储平台地址 其他平台可自行更改
    然后就是做一个本地缓存用的假文件
    接着到 异常里
    先做存储平台的链接,然后获取要下载文件的大小
    获取大小后 更具线程数量 自行计算启动多少个线程来下载 我这里直接给的100 然后使用for进行线程的启动 启动后进入线程等待 全执行完之后 可正常生成文件,

    然后就是线程使用的分片下载工具类

    
    /**
     * .
     *
     * @ClassName: BigFileDownloadRunnable
     * @Description:
     * @Author: LXT
     * @Date: 2021/12/27 13:19
     */
    
    class BigFileDownloadRunnable implements Runnable {
    
        private String endpoint;
    
        private String accessKey;
    
        private String secretKey;
    
        private String bucketName;
    
        private long from;
    
        private long end;
    
        private RandomAccessFile file;
    
        private String downloadFilePath;
    
        public BigFileDownloadRunnable(long from, long end, RandomAccessFile file,
                                       String endpoint, String accessKey, String secretKey, String bucketName,String downloadFilePath) {
            this.from = from;
            this.end = end;
            this.file = file;
            this.endpoint = endpoint;
            this.accessKey = accessKey;
            this.secretKey = secretKey;
            this.bucketName = bucketName;
            this.downloadFilePath = downloadFilePath;
        }
    
        public void run() {
    
            String filename = downloadFilePath;
            S3Object objectPortion = null;
            InputStream input = null;
            BufferedInputStream buffer = null;
            try {
                AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
                ClientConfiguration clientConfig = new ClientConfiguration();
                clientConfig.setProtocol(Protocol.HTTP);
                clientConfig.setConnectionTimeout(90000000);
                clientConfig.setMaxConnections(1000);
                AmazonS3 s3Client = new AmazonS3Client(credentials, clientConfig);
                s3Client.setEndpoint(endpoint);
                //获取对象指定范围的流写入文件
                GetObjectRequest rangeObjectRequest = new GetObjectRequest(bucketName, filename).withRange(from, end);
                objectPortion = s3Client.getObject(rangeObjectRequest);
    
                input = objectPortion.getObjectContent();
                buffer = new BufferedInputStream(input);
    
                byte[] buf = new byte[1024];
                int len;
                long start = this.from;
                long stop = this.end;
                for (; ; ) {
                    if ((len = buffer.read(buf)) == -1) {
                        break;
                    }
                    synchronized (file) {
                        file.seek(from);
                        file.write(buf, 0, len);
                    }
                    from += len;
                }
                System.out.println("文件片段 " + start + "~" + stop + "下载完成");
                new BigFileDownload().latch.countDown();//线程结束计数器减1
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                if (buffer != null) {
                    try {
                        buffer.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if (objectPortion != null) {
                    try {
                        objectPortion.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    

    因为线程分段 也需要去请球平台 所以就将平台的数据一并传输过来

    然后线程内run 大概意思 就是 我拿到了平台链接 然后又有文件的存错位置 还有我需要下载的片段位置,然后就是正常下载过程

    由于大文件比较大 链接时间设置的相对较长一点,

    一小点的进步都是对开发者的激励,记录一下,分享给大家。有用记得点♥

    展开全文
  • 本篇文章主要介绍了Spring boot实现文件上传实例(文件上传),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • .net ftp多线程批量文件上传服务
  • 主要介绍了C# 文件上传下载(Excel导入,多线程下载)功能的实现代码,需要的朋友可以参考下
  • 使用java socket开发的多线程文件上传下载的实例项目,多线程并发测试中可以支持200个,可能由于我电脑的配置问题,一般在并发大于200时client端可能会出现"阻塞"问题,还请大家指教
  • Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。 从官网的描述我们可以简单的概括,Electron是开源的框架,可以使用h5来开发跨平台pc桌面...
  • 使用线程池管理多线程上传,包含了文件拆分,文件分片多线程上传,单文件上传多线程执行任务等待管理。拒绝直接new Thread创建新线程导致的诸多问题
  • 主要介绍了Java多线程文件分片下载实现的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • java多线程加队列上传文件_后台处理
  • 五个package包,11个类文件 服务器入口 : com.hz.chang.server_server.ServerAction 直接运行就ok 客户端入口: com.hz.chang.server_client.ClientAction 运行时需要输入一个并发数 建议导出客户端jar文件,以便...
  • github:https://github.com/xiaofengyun/FTP-FILE-transport ... 无线网络下基于FTP文件存储系统运行环境如下: 开发平台:Windows 10(客户端),Linux(服务端) 开发环境:Qt Creator,Ce...

    github:https://github.com/xiaofengyun/FTP-FILE-transport

                 https://github.com/xiaofengyun/FTP-FILE-transport.git

    无线网络下基于FTP文件存储系统运行环境如下:
    开发平台:Windows 10(客户端),Linux(服务端)
    开发环境:Qt Creator,Centos 7
    编译环境:G++,GDB,qmake
    运行环境:Qt 5.5.1,Centos 7

    多线程上传的逻辑:

    选择完一个文件后,通过偏移文件指针lseek()得到文件的size。接下来将大文件按照一定的方法拆分,首先,先比较文件的大小与切片大小,切片大小是一个定值。如果文件的大小小于切片的大小,那么不必进行多线程上传,单线程就可以了。当需要多线程上传的时候,首先计算出线程个数,通过用size/切片大小和size%切片大小的方式计算出需要的线程数。接下来便是传输文件,使用read()函数按字节去读取文件,每次读取一定的字节数到一个缓冲区。然后便是加标志位。犹豫线程是并发执行的,无法预测哪一个线程会首先完成传输,这会对文件的合并差生巨大的影响,所以必须加上标志位,判断数据片段是属于哪一个位置的。在缓冲区的前两个字节加上线程ID作为标志位,然后将读取的文件数据凭借到缓冲区后面,这样便组成了一个数据包,每个线程将这个数据包发送给服务端,然后自行关闭。

    客户端多线程上传程序:

    void MainWindow::thread_upload()/多线程上传
    {
    	qDebug() << "start thread upload...";
    	qint64 m_totalBytes;
    	QFile * m_localFile;
    
    	QString path = QFileDialog::getOpenFileName(this, "Open a file", "/", "files (*)");
    	QFileInfo info(path);//path就是打开文件的路径
    
    	m_localFile = new QFile(path);//类似一个文件指针
    	if (!m_localFile->open(QFile::ReadOnly))
    	{
    		qDebug() << "open file error!";
    		return;
    	}
    	//打开成功
    	qDebug() << "打开文件成功!";
    	m_totalBytes = m_localFile->size();//得到文件总大小
    	QString size = QString::number(m_totalBytes, 10);
    	qDebug() << "文件大小:" << m_localFile->size();
    	QString up = "upload";
    	up += " " + info.fileName() + " " + size;
    
    	char*  ch;
    	QByteArray ba = up.toLatin1(); // must
    	ch = ba.data();
    	sockfd->write(ch);///向服务端发送上传请求,等待回应
    	if (sockfd->waitForReadyRead(10))
    	{
    		QByteArray buff = sockfd->readAll();//接收服务端返回的消息
    		qDebug() << buff;
    		if (strncmp(buff, "ok", 2) != 0)
    		{
    			qDebug() << "server no message...";
    			return;
    		}
    		int n = 0;
    		int i = 0;
    		threadDown *thread[SIZE];
    		char sendbuff[1024] = { 0 };
    		size_int = size.toInt();
    		qDebug() << "size=" << size_int;
    		int num_thread = size_int / 1000;1000为分片大小,大小自己定义
    		if (size_int - num_thread * 1000>0)
    		{
    			num_thread++;///需要开启的线程数,也就是分片的个数
    		}
    		qDebug() << "thread=" << num_thread;
    
    		for (; i<num_thread; i++)
    		{
    			qDebug() << "i=" << i;
    
    			if (i <= 9)
    			{
    				sprintf(sendbuff, "%d", i);
    				sprintf(sendbuff + 1, "%s", NULL);
    			}
    			else
    			{
    				sprintf(sendbuff, "%d", i);
    			}
    			n = m_localFile->read(sendbuff + 2, 1000);每个数据包的前两个字节表示线程id,也就是标识符
    	
    			thread[i] = new threadDown(sendbuff, i); //新建线程对象,在线程中将数据发送就可以了
    			thread[i]->start();  //启动线程
    			bool b = connect(thread[i], SIGNAL(thread_to_main(char *, int)), this, SLOT(start_to_up(char *, int)));
    			qDebug() << "b=" << b;
    			thread[i]->wait();
    			memset(sendbuff, 0, sizeof(sendbuff));
    			qDebug() << "------------------------------------------------------------";
    		}	
    	}
    
    //多线程上传时,服务端接收处理程序
    while ((num = recv(c, buff, 1002, 0))>0)
    {
    	printf("num =%d\n", num);
    	printf("%s\n", buff);
    	char seq[2] = "";
    	seq[0] = buff[0];
    	seq[1] = buff[1];
    	//cout<<"seq="<<seq;
    	printf("seq=%s\n", seq);
    	int pro_seq = atoi(seq);//求出线程数
    	printf("id =%d\n", pro_seq);
    	cout++;
    	num -= 2;
    	printf("%s\n", buff);
    	printf("len=%d\n", strlen(buff));
    	cur_size += num;
    	printf("cur_size=%d\n", cur_size);
    
    	printf("线程id=%d\n", pro_seq);
    
    	int off = lseek(fd, pro_seq * 1000, SEEK_SET);//偏移到原本数据分片的地方
    	printf("偏移字节=%d\n", off);
    
    	write(fd, buff + 2, strlen(buff) - 2);
    	memset(buff, 0, sizeof(buff));
    	lseek(fd, 0, SEEK_SET);//指针重置
    	printf("-----------------------------------=--------------\n");
    	printf("cur_size=%d\n", cur_size);
    	if (cur_size >= size)
    	{
    		break;
    	}
    }

    多文件下载:

    为了实现多文件同时下载,采用了多客户端程序连接服务端的方式。前面提到过,服务端可以承受多客户端的连接,所以当有多个文件去下载时,表面上是由一个用户发出的请求,在内部实现时,模拟多用户去下载的过程。

    步骤:

    1.开启多个线程,将要下载的文件名传入各个线程;

    2.再线程函数中创建套接字去下载文件即可。

    运行截图:

     

    代码在git里面,需要借鉴的可以看。代码完全是本人自己的想法,如有不对或者错误请指正,交流加QQ:965829642.

    展开全文
  • 1、构建FTP客户端 package cn.com.pingtech.common.ftp; import lombok.extern.slf4j.Slf4j; import org.apache.commons.net.ftp.FTPClient;...import org.apache.commons.net.ftp.FTPReply;...public class Ftp

    1、构建FTP客户端

    
    
    
    package cn.com.pingtech.common.ftp;
    
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.net.ftp.FTPClient;
    import org.apache.commons.net.ftp.FTPReply;
    
    import java.io.*;
    import java.net.UnknownHostException;
    
    @Slf4j
    public class  FtpConnection {
    
        private FTPClient ftp = new FTPClient();
    
        private boolean is_connected = false;
    
        /**
         * 构造函数
         */
        public FtpConnection() {
            is_connected = false;
            ftp.setDefaultTimeout(FtpConfig.defaultTimeoutSecond * 1000);
            ftp.setConnectTimeout(FtpConfig.connectTimeoutSecond * 1000);
            ftp.setDataTimeout(FtpConfig.dataTimeoutSecond * 1000);
            try {
                initConnect(FtpConfig.host, FtpConfig.port, FtpConfig.user, FtpConfig.password);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 初始化连接
         *
         * @param host
         * @param port
         * @param user
         * @param password
         * @throws IOException
         */
        private void initConnect(String host, int port, String user, String password) throws IOException {
            try {
                ftp.connect(host, port);
            } catch (UnknownHostException ex) {
                throw new IOException("Can't find FTP server '" + host + "'");
            }
            int reply = ftp.getReplyCode();//220 连接成功
            if (!FTPReply.isPositiveCompletion(reply)) {
                disconnect();
                throw new IOException("Can't connect to server '" + host + "'");
    
            }
            if (!ftp.login(user, password)) {
                is_connected = false;
                disconnect();
                throw new IOException("Can't login to server '" + host + "'");
            } else {
                is_connected = true;
            }
        }
    
        /**
         * 上传文件
         *
         * @param path
         * @param ftpFileName
         * @param localFile
         * @throws IOException
         */
        public boolean upload(String path, String ftpFileName, File localFile) throws IOException {
            boolean is  = false;
            //检查本地文件是否存在
            if (!localFile.exists()) {
                throw new IOException("Can't upload '" + localFile.getAbsolutePath() + "'. This file doesn't exist.");
            }
            //设置工作路径
            setWorkingDirectory(path);
            //上传
            InputStream in = null;
            try {
                //被动模式
                ftp.enterLocalPassiveMode();
                in = new BufferedInputStream(new FileInputStream(localFile));
                //保存文件
                is = ftp.storeFile(ftpFileName, in);
            }catch (Exception e){
                e.printStackTrace();
            }
            finally {
                try {
                    in.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            return is;
        }
    
        /**
         * 关闭连接
         *
         * @throws IOException
         */
        public void disconnect() throws IOException {
            if (ftp.isConnected()) {
                try {
                    ftp.logout();
                    ftp.disconnect();
                    is_connected = false;
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    
        /**
         * 设置工作路径
         *
         * @param dir
         * @return
         */
        private boolean setWorkingDirectory(String dir) {
            if (!is_connected) {
                return false;
            }
            //如果目录不存在创建目录
            try {
                if (createDirecroty(dir)) {
                    return ftp.changeWorkingDirectory(dir);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
    
        }
    
        /**
         * 是否连接
         *
         * @return
         */
        public boolean isConnected() {
            return is_connected;
        }
    
        /**
         * 创建目录
         *
         * @param remote
         * @return
         * @throws IOException
         */
        private boolean createDirecroty(String remote) throws IOException {
            boolean success = true;
            String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
            // 如果远程目录不存在,则递归创建远程服务器目录
            if (!directory.equalsIgnoreCase("/") && !ftp.changeWorkingDirectory(new String(directory))) {
                int start = 0;
                int end = 0;
                if (directory.startsWith("/")) {
                    start = 1;
                } else {
                    start = 0;
                }
                end = directory.indexOf("/", start);
                while (true) {
                    String subDirectory = new String(remote.substring(start, end));
                    if (!ftp.changeWorkingDirectory(subDirectory)) {
                        if (ftp.makeDirectory(subDirectory)) {
                            ftp.changeWorkingDirectory(subDirectory);
                        } else {
                            log.error("mack directory error :/" + subDirectory);
                            return false;
                        }
                    }
                    start = end + 1;
                    end = directory.indexOf("/", start);
                    // 检查所有目录是否创建完毕
                    if (end <= start) {
                        break;
                    }
                }
            }
            return success;
        }
    
    
    
    }
    
    

    2、FTP连接工厂

    
    package cn.com.pingtech.common.ftp;
    
    import lombok.extern.slf4j.Slf4j;
    
    import java.io.IOException;
    import java.util.concurrent.ArrayBlockingQueue;
    
    
    /**
     * 连接工厂
    
     */
    @Slf4j
    public class FtpFactory {
    
        //有界队列
        private static final ArrayBlockingQueue<FtpConnection> arrayBlockingQueue = new ArrayBlockingQueue<>(FtpConfig.ftpConnectionSize);
    
    
        protected FtpFactory(){
            log.info("init ftpConnectionSize "+FtpConfig.ftpConnectionSize);
            for(int i = 0; i< FtpConfig.ftpConnectionSize; i++){
                //表示如果可能的话,将 e 加到 BlockingQueue 里,即如果 BlockingQueue 可以容纳,则返回 true,否则返回 false
                arrayBlockingQueue.offer(new FtpConnection());
            }
        }
    
        /**
         * 获取连接
         *
         * @return
         */
    
        public FtpConnection getFtp() {
            FtpConnection poll = null;
            try {
                //取走 BlockingQueue 里排在首位的对象,若 BlockingQueue 为空,阻断进入等待状态直到 Blocking 有新的对象被加入为止
                poll = arrayBlockingQueue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return poll;
        }
    
        /**
         * 释放连接
         * @param ftp
         * @return
         */
        public boolean relase(FtpConnection ftp){
            return arrayBlockingQueue.offer(ftp);
        }
    
        /**
         * 删除连接
         *
         * @param ftp
         */
    
        public void remove(FtpConnection ftp) {
            arrayBlockingQueue.remove(ftp);
        }
    
        /**
         * 关闭连接
         */
        public void close() {
            for (FtpConnection connection : arrayBlockingQueue) {
                try {
                    connection.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
    }
    
    

    3、FTP配置

    
    
    package cn.com.pingtech.common.ftp;
    
    /**
     * ftp 配置类
     */
    
    public class FtpConfig {
    
        public static int defaultTimeoutSecond = 10;
    
        public static int connectTimeoutSecond = 10;
    
        public static int dataTimeoutSecond = 10;
    
        public static String host = "127.0.0.1";
    
        public static int port =9999;
    
        public static String user = "Administrator";
    
        public static String password ="Yp886611";
    
        public static int threadPoolSize = 1;
    
        public static int ftpConnectionSize = 1;
        
    }
    
    
    

    4、构建多线程FTP上传任务

    package cn.com.pingtech.common.ftp;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.concurrent.Callable;
    
    
    /**
     * 上传任务
     */
    public class UploadTask implements Callable{
        private File file;
    
        private FtpConnection ftp;
    
        private String path;
    
        private String fileName;
    
        private FtpFactory factory;
    
        public UploadTask(FtpFactory factory,FtpConnection ftp, File file, String path, String fileName){
    
            this.factory = factory;
    
            this.ftp = ftp;
    
            this.file = file;
    
            this.path = path;
    
            this.fileName = fileName;
    
        }
    
        @Override
        public UploadResult call() throws Exception {
            UploadResult result = null;
            try {
                if (ftp == null) {
                    result = new UploadResult(file.getAbsolutePath(), false);
                    return result;
                }
                //如果连接未开启 重新获取连接
                if (!ftp.isConnected()) {
                    factory.remove(ftp);
                    ftp = new FtpConnection();
                }
    
                //开始上传
                result = new UploadResult(file.getName(), ftp.upload(path, fileName, file));
            } catch (IOException ex) {
                result = new UploadResult(file.getName(), false);
                ex.printStackTrace();
            } finally {
                factory.relase(ftp);//释放连接
            }
            return result;
    
        }
    }
    
    package cn.com.pingtech.common.ftp;
    /**
     * 上传结果
     */
    public class UploadResult {
        private String fileName; //文件名称
        private boolean result; //是否上传成功
    
        public UploadResult(String fileName, boolean result) {
            this.fileName = fileName;
            this.result = result;
        }
    
        public String getFileName() {
            return fileName;
    
        }
    
        public void setFileName(String fileName) {
            this.fileName = fileName;
        }
    
        public boolean isResult() {
            return result;
        }
    
        public void setResult(boolean result) {
            this.result = result;
        }
    
        public String toString() {
            return "[fileName=" + fileName + " , result=" + result + "]";
        }
    }
    

    注意:实现Callable接口的任务线程能返回执行结果
    Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞线程直到获取“将来”的结果,当不调用此方法时,主线程不会阻塞

    5、FTP上传工具类

    
    
    package cn.com.pingtech.common.ftp;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;
    
    
    /**
     * ftp上传工具包
     */
    
    public class FtpUtil {
    
        /**
         * 上传文件
         *
         * @param ftpPath
         * @param listFiles
         * @return
         */
    
        public static synchronized List upload(String ftpPath, File[] listFiles) {
            //构建线程池
            ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(FtpConfig.threadPoolSize);
            List<Future> results = new ArrayList<>();
            //创建n个ftp链接
            FtpFactory factory = new FtpFactory();
            for (File file : listFiles) {
                FtpConnection ftp = factory.getFtp();//获取ftp con
                UploadTask upload = new UploadTask(factory,ftp, file, ftpPath, file.getName());
                Future submit = newFixedThreadPool.submit(upload);
                results.add(submit);
            }
    
            List listResults = new ArrayList<>();
            for (Future result : results) {
                try {
                    //获取线程结果
                    UploadResult uploadResult = (UploadResult)result.get(30, TimeUnit.MINUTES);
                    listResults.add(uploadResult);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            factory.close();
            newFixedThreadPool.shutdown();
            return listResults;
        }
    
    }
    
    
    

    6、测试上传

    package cn.com.pingtech.common.ftp
    
    
    class Client {
        public static void main(String[] args) throws IOException {
            String loalPath = "C:\\Users\\Administrator\\Desktop\\test\\0";
            String ftpPath = "/data/jcz/";
            File parentFile = new File(loalPath);
            List <UploadResult> list = FtpUtil.upload(ftpPath,parentFile.listFiles());
            for(UploadResult vo:list){
                System.out.println(vo);
            }
            
        }
    }
    
    

    注意:FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码

    展开全文
  • qt 多线程实现样例,实现文件的拷贝,亲测可用,重新编译即可
  • 文件上传需要保证数据的安全性、完成性以及连接性,所以使用 TCP 协议来实现,这里就以上传一张图片文件为例,分别使用单线程和多线程实现,单线程就是一个服务器接收一个客户端发来的图片,多线程就是一个...
  • C# 多线程文件上传和下载工具源码(含FTP/SMTP/MSMQ/ActiveMQ的接收与发送)
  • 主要介绍了C#实现多线程下载文件的方法,实例分析了C#多线程文件传输的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 主要介绍了Android实现多线程下载文件的方法,以实例形式较为详细的分析了Android多线程文件传输及合并等操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • NULL 博文链接:https://logicluo.iteye.com/blog/2196661
  • C++网络编程实例文件,里面包含各个章节的C++源码。 第一章 网络通信基础 第二章 认识Windows编程模型...第十章 多线程网络文件传输的设计与实现 第十一章 防火墙的设计与实现 第十二章 邮件转发器 第十三章 telnet bbs

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 268,745
精华内容 107,498
关键字:

多线程实现大文件上传