#include "fileOperation.h"
#include <iostream>
#include <string.h>
using namespace std;
long bufSize = 10 * 1024; // 缓冲区大小
char* buffer; // 缓冲区保存文件数据
long sendedLength; // 客户端已经保存的数据长度
bool sendFile(SOCKET s, char* filePath,bool isDir)
{
if (isDir)
{
// 如果传进来的是文件夹
std::vector<std::string> vecFileInfo;
findEx(filePath, vecFileInfo);
if (vecFileInfo.size() > 0)
{
for (int i = 0; i < vecFileInfo.size(); i++)
{
char* fileName = new char[256];
memset(fileName, 0, 256);
strcpy(fileName, (char*)vecFileInfo.at(i).c_str());
// 发送文件的完整路径名给client,用于创建文件夹和文件
char* filePathBuf = new char[256];
// 去掉server端的用户选中的文件夹
string strSrc(fileName);
string strOld(filePath);
string new_path = replace_all(strSrc, strOld, ".");
strcpy(filePathBuf, (char*)new_path.c_str());
// 获取服务器上的文件大小
FILE* read = fopen(fileName, "rb");
if (!read)
{
perror("file open failed:\n");
return false;
}
long lFileSize = 0;
fseek(read, 0, SEEK_END);
lFileSize = ftell(read);
fseek(read, 0, SEEK_SET);
char dataLength[32];
memset(dataLength, 0, 32);
ltoa(lFileSize, dataLength,10);
char header[256];
memset(header, 0, 256);
strcat(header, filePathBuf);
strcat(header, "$");
strcat(header, dataLength);
// 发送文件名称包括文件目录给client
send(s, header, strlen(header),0);
//long lLength = -2;
recvRemoteFileLength(s, fileName);
// 获取文件大小
if (sendedLength == 0)
{
fseek(read, 0, SEEK_END);
bufSize = ftell(read);
fseek(read, 0, SEEK_SET);
cout << "filesize:" << bufSize << endl;
}
else
{
fseek(read, 0, SEEK_END);
bufSize = ftell(read) - sendedLength;
//fseek(read, 0, SEEK_SET);
fseek(read, sendedLength, SEEK_CUR);
if (bufSize <= 0)
{
fclose(read);
memset(buffer, 0, bufSize);
continue;
}
cout << "78 sendedLength filesize: " << bufSize << endl;
}
// 把文件读取到内存中
buffer = new char[bufSize];
//cout << sizeof(buffer) << endl;
if (!buffer)
{
return false;
}
int nCount;
int ret = 0;
while ((nCount = fread(buffer, 1, bufSize, read)) > 0)
{
ret += send(s, buffer, nCount, 0);
if (ret == SOCKET_ERROR)
{
err("sendFile");
return false;
}
}
//shutdown(s, SD_SEND);
recv(s, buffer, bufSize, 0);
fclose(read);
memset(buffer, 0, bufSize);
cout << "send file success!" << "Byte:" << ret << endl;
}
}
}
else
{
const char* fileName = filePath;
// 发送文件名称包括文件目录给client
string strFileName(fileName);
int index = strFileName.find_last_of("/");
string strLastFileName = strFileName.substr(index);
strLastFileName = "./" + strLastFileName;
// 获取文件大小
FILE* read = fopen(fileName, "rb");
if (!read)
{
perror("file open failed:\n");
return false;
}
long lFileSize = 0;
fseek(read, 0, SEEK_END);
lFileSize = ftell(read);
fseek(read, 0, SEEK_SET);
// 拼接文件目录和大小
char dataLength[32];
memset(dataLength, 0, 32);
ltoa(lFileSize, dataLength, 10);
char header[256];
memset(header, 0, 256);
strcat(header, strLastFileName.c_str());
strcat(header, "$");
strcat(header, dataLength);
send(s, header, strlen(header), 0);
recvRemoteFileLength(s, fileName);
// 获取文件大小
if (sendedLength == 0)
{
fseek(read, 0, SEEK_END);
bufSize = ftell(read);
fseek(read, 0, SEEK_SET);
cout << "filesize:" << bufSize << endl;
}
else
{
fseek(read, 0, SEEK_END);
bufSize = ftell(read) - sendedLength;
//fseek(read, 0, SEEK_SET);
fseek(read, sendedLength, SEEK_CUR);
cout << "sendedLength filesize: " << bufSize << endl;
}
// 把文件读取到内存中
buffer = new char[bufSize];
cout << " 154 == "<< sizeof(buffer) << endl;
if (!buffer)
{
return false;
}
int nCount;
int ret = 0;
while ((nCount = fread(buffer, 1, bufSize, read)) > 0)
{
ret += send(s, buffer, nCount, 0);
if (ret == SOCKET_ERROR)
{
err("sendFile");
return false;
}
}
//shutdown(s, SD_SEND);
recv(s, buffer, bufSize, 0);
fclose(read);
memset(buffer, 0, bufSize);
cout << "send file success!" << "Byte:" << ret << endl;
}
return true;
}
bool recvFile(SOCKET s,char* savePath)
{
// 接收server发送过来的文件路径,包括文件名
char* fileName = new char[256];
char* pathBuf = new char[256];
memset(pathBuf, 0, 256);
char pathBufEx[256];
memset(pathBufEx, 0, 256);
recv(s,pathBuf,256,0); // 获取到的路径是D:\\1\\,这种双反斜杠的格式
char payloadLength[32];
memset(payloadLength, 0, 32);
for (int i = 0; i < strlen(pathBuf); i++)
{
if (pathBuf[i] == '$')
{
for (int j = 0; j < 32; j++)
{
if (pathBuf[i + 1 + j] != '\0')
{
payloadLength[j] = pathBuf[i + 1 + j];
}
else
{
break;
}
}
break;
}
else
{
pathBufEx[i] = pathBuf[i];
}
}
if (payloadLength != nullptr && strlen(payloadLength) == 0)
{
return false;
}
long fileLength = atol(payloadLength);
cout << "167 == " << pathBufEx << " fileLength == "<< fileLength << endl;
if (pathBufEx == nullptr || pathBufEx == "")
{
return false;
}
if (strstr(pathBufEx, "\\") != NULL)
{
replace_str(pathBufEx, '\\\\', '/');
}
// 把接收到的文件夹目录加上本地的文件夹路径
strcat(savePath, "/");
std::string strA(pathBufEx);
std::string strB(savePath);
std::string strLocalPath = replace_all(strA,"./",strB);
int index = strLocalPath.find_last_of("/");
string new_local_path = strLocalPath.substr(0, index);
// 创建子文件夹和文件
createDirs((char*)new_local_path.c_str());
strcpy(fileName,strLocalPath.c_str());
cout << "187 == " << fileName << endl;
if (buffer == NULL)
{
buffer = new char[bufSize];
if (!buffer)
{
return false;
}
}
// 创建空文件
FILE* write = fopen(fileName, "ab+");
if (!write)
{
perror("file write failed:\n");
return false;
}
// 发送该文件是否在客户端存在,用于断点续传
sendLocalFileLength(s, fileName);
int ret = 0;
int nCount;
long fileLastLength = 0;
fileLastLength = fileLength - sendedLength; // 文件总大小减去已经发送的文件大小
if (fileLastLength <= 0)
{
fclose(write);
return true;
}
while ((nCount = recv(s, buffer, bufSize, 0)) > 0)
{
ret = fwrite(buffer, nCount, 1, write);
fileLastLength -= nCount;
if (fileLastLength <= 0)
{
break;
}
}
if (ret == 0)
{
cout << "server offline" << endl;
}
else if (ret < 0)
{
err("recv");
return false;
}
cout << "receive file success!" << endl;
char lastBuf[1] = { '1' };
send(s, lastBuf, 1, 0);
fclose(write);
cout << "save file success! Filename:" << fileName << endl;
//system("pause");
return true;
}
bool sendLocalFileLength(SOCKET s, const char * fileName)
{
long localFileLength = 0;
FILE* read = fopen(fileName, "rb");
char buf[32] = { 0 };
if (!read)
{
perror("236 file open failed:\n");
localFileLength = 0;
}
else
{
// 获取本地文件的大小
fseek(read, 0, SEEK_END);
localFileLength = ftell(read);
fseek(read, 0, SEEK_SET);
cout << "localFileLength:" << localFileLength << endl;
}
ltoa(localFileLength, buf, 10);
if ((send(s, buf, strlen(buf), 0)) > 0)
{
cout << "localFileLength 6666:" << localFileLength;
sendedLength = localFileLength;
return true;
}
else
{
sendedLength = 0;
}
return false;
}
long recvRemoteFileLength(SOCKET s, const char * fileName)
{
char* buf = new char[32];
if (!buf)
{
return 0;
}
int nCount = recv(s, buf, 32, 0);
if (nCount > 0)
{
sendedLength = atol(buf);
}
else
{
// 没�
C++实现断点续传,单线程
需积分: 5 152 浏览量
2023-07-28
09:29:15
上传
评论
收藏 8KB RAR 举报
video_plugin_yue
- 粉丝: 120
- 资源: 6
最新资源
- 1_提高高温超导体的临界温度的方法_pdf_1629817512307_9.jpg
- 用户故事示例导入模板(官网示例)
- 1_提高高温超导体的临界温度的方法_pdf_1629817510190_0.jpg
- Java实现计数排序算法(源代码)
- 这个 ide98 是适合老式机器上用到的一个补充文件,文件的过程代表过程的文件这个 ide98 是适合老式机器上用到的一个补充文
- 866164937784007CarLife3.0车机修改版支持无线和方控.apk
- 天津理工大学-操作系统实验3:磁盘调度算法的实现.doc
- 天津理工大学数据库期末复习试题一.doc
- 花农科技的驱动整合,ide98,这个工具可以用来修改计算机,修改后的计算机会更好用的,多合一,很好用,很实用
- 天猫电子商务案例分析-PPT.ppt
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈