A masz:
class socket_buffer:public std::streambuf
{
public:
int underflow()
{
int bytes_read = socket.Read(buffer, sizeof(buffer));
if(bytes_read <= 0) return EOF;
setg(buffer, buffer, buffer + bytes_read);
return *buffer;
}
socket_buffer(NetSock &socket_)
:socket(socket_)
{
underflow();
}
private:
NetSock &socket;
char buffer[2048];
};
bool downloadFile(NetSock &n, const string &file, const string &where)
{
std::ostringstream oss;
oss << "GET " << file << " HTTP/1.1\r\n"
<< "Host: " << "cdimage.debian.org" << "\r\n"
<< "Connection: Keep-Alive\r\n"
<< "\r\n";
std::string s = oss.str();
if(n.WriteAll(s.c_str(), s.size()) <= 0) return false;
socket_buffer sbuf(n);
std::istream is(&sbuf);
int total_data_len = -1;
while(std::getline(is, s) && s.size() > 1)
{
std::istringstream iss(s);
std::string name;
std::getline(iss, name, ':');
if(name == "Content-Length")
iss >> total_data_len;
}
if(total_data_len == -1)return false;
std::ofstream ofs(where, std::ios::binary);
char buff[1024];
while(total_data_len > 0 && is.read(buff, std::min(1024, total_data_len)))
{
ofs.write(buff, is.gcount());
total_data_len -= is.gcount();
}
return total_data_len == 0;
}
Funkcja jest niechlujnie napisana i nie wiem, czy zadziała na kontencie binarnym, ale dla tych plików działa :)
PS. nie chciało mi się kombinować, żeby istream
na moim bufforze konwertował \r\n
na \n
, dlatego czytane linie będą zawierać \r
na końcu.