Bootstrap

基于Qt开发的云盘(客户端篇)

开发的最初意图很简单,就是方便从台式传输小电影到笔记本上(狗头狗头)

其实就是懒得下载第三方软件了,然后看着百度网盘发呆半个小时后,就打算搞一个出来自己用。
后来用习惯了发现局域网环境下多方共享文件YYDS,速度基本上跑满带宽,杠杠滴。

如果自己有固定IP的外网存储,也可以直接拿来当点对点传输使用。

直接上效果吧

整体看功能是比较简单的,上传、下载、删除、搜索等。还可以检测服务端的容量情况

为了能同时上传和下载更多小电影,我建了个线程池,开启了多线程上传下载,示例代码如下:

QThread * CTcpMultiThreadPool::getFreeThread()
{
    QThread *pthread = NULL;
    auto begin = haAllThread.begin();
    for (begin; begin != haAllThread.end(); ++begin)
    {
        if (begin.value() < MAX_VALUE)
        {
            m_CurThread = begin;
            m_CurThread.value()++;
            pthread = m_CurThread.key();
            break;
        }
    }
    return pthread;
}

 传输使用了自定义的协议,先传输文件信息,再传输文件的二进制数据

void FileHandleThread::getStartTransferSlot()
{
	if (!init())
	{
		emit sendConnentStateFailSignal(false);
		closeConnect();
		return;
	}
	if (m_type == 1)
	{
		QFile file(m_FileInfo.FilePath);
		file.open(QIODevice::ReadOnly);
		m_FileBuf.resize(SEND_BLOCK_SIZE + 128);
		QByteArray head = getHead(m_FileInfo, 1) + "###";

		m_FileBuf = head + file.read(SEND_BLOCK_SIZE);

		m_SendSize = m_Socket->write(m_FileBuf);
		m_Socket->waitForBytesWritten(3000);
		m_SendSize = m_SendSize - head.size();
		qint64 fileSize = m_FileInfo.FileSize.toLongLong();
		emit sendProcessPercentSignal(m_SendSize);
		if (m_SendSize < fileSize)
		{
			do
			{
				if (DenyFlag)
				{
					m_SaveFile.close();
					closeConnect();
					return;
				}
				while (StopTransferFlag)
				{
					if (DenyFlag)
					{
						m_SaveFile.close();
						closeConnect();
						return;
					}
				}
				m_FileBuf = file.read(SEND_BLOCK_SIZE);
				m_SendSize += m_Socket->write(m_FileBuf);
				m_Socket->waitForBytesWritten(3000);
				emit sendProcessPercentSignal(m_SendSize);
			} while (m_SendSize  < fileSize);
		}
		emit sendFinishSignal();
		closeConnect();
	}
	else if (m_type == 2)
	{
		QByteArray head = getHead(m_FileInfo, 2) + "###";
		int size = m_Socket->write(head);
		m_Socket->waitForBytesWritten(3000);
		m_ReceiveLen = 0;
	}
}

还加入了中途取消上传和下载的功能


void TransfersInfo::getDenyTransferSlot(const QString & md5, int type)
{
	QMutexLocker locker(&gTasksMutex);
	ControlWidget *wg = nullptr;
	QListWidgetItem *item = nullptr;
	if (type == 1)
	{
		for (int i = 0; i < m_UploadListWidget->count(); i++)
		{
			if (m_UploadListWidget->item(i)->whatsThis().compare(md5) == 0)
			{
				item = m_UploadListWidget->item(i);
				m_UploadListWidget->takeItem(i);
				delete item;
				break;
			}
		}
		disconnect(m_UploadListMapControlWidget[md5], &ControlWidget::sendTransferFinishSignal, this, &TransfersInfo::getTransferFinishSlot);
		disconnect(m_UploadListMapControlWidget[md5], &ControlWidget::sendDenyTransferInfoSignal, this, &TransfersInfo::getDenyTransferSlot);
		wg = m_UploadListMapControlWidget[md5];
		m_UploadListMapControlWidget.erase(md5);
		m_UploadMap.erase(md5);
		if (wg)
		{
			delete wg;
		}
	}
	else if (type == 2)
	{
		for (int i = 0; i < m_DownLoadListWidget->count(); i++)
		{
			if (m_DownLoadListWidget->item(i)->whatsThis().compare(md5) == 0)
			{
				item = m_DownLoadListWidget->item(i);
				m_DownLoadListWidget->takeItem(i);
				delete item;
				break;
			}
		}
		disconnect(m_DownloadListMapControlWidget[md5], &ControlWidget::sendTransferFinishSignal, this, &TransfersInfo::getTransferFinishSlot);
		disconnect(m_DownloadListMapControlWidget[md5], &ControlWidget::sendDenyTransferInfoSignal, this, &TransfersInfo::getDenyTransferSlot);
		wg = m_DownloadListMapControlWidget[md5];
		m_DownloadListMapControlWidget.erase(md5);
		m_DownloadMap.erase(md5);
		if (wg)
		{
			delete wg;
		}
	}
}

大致就那么多吧,很久之前写的了,回忆一下

;