1
私はウェブサイトから画像をダウンロードしようとしています。問題は、HTTP応答本体からすべてのコンテンツを取得しても、ファイルが開かないということです。私はこれを解決しようとしてきましたが、本当の問題を見つけることはできません。私が気付いたことの一つは、chromiumを使ってダウンロードした画像は、コマンドを使ってコードからダウンロードした画像とは異なる文字を表示することです。 $ cat picture.png |ここではあまり
C++ HTTP応答から画像を取得
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
using std::cout;
using std::endl;
//with this function I remove HTTP header info, so I only get content.
char *removeHTTPHeader(char *buffer) {
char *t = strstr(buffer, "\r\n\r\n");
t = t + 4;
return t;
}
void getPicture(const int &socketfd, const int &bSize) {
std::ofstream file("picture.png",
std::ofstream::binary | std::ofstream::out);
char buffer[bSize];
ssize_t bReceived;
bReceived = recv(socketfd, buffer, bSize, 0);
char *t = removeHTTPHeader(buffer);
file.write(t, strlen(t));
memset(buffer, 0, bSize);
while ((bReceived = recv(socketfd, buffer, bSize, 0)) > 0) {
file.write(buffer, bReceived);
memset(buffer, 0, bSize);
}
file.close();
}
int main() {
int status;
addrinfo host_info;
addrinfo *host_info_list;
memset(&host_info, 0, sizeof(host_info));
host_info.ai_family = AF_UNSPEC;
host_info.ai_socktype = SOCK_STREAM;
host_info.ai_protocol = 0;
status = getaddrinfo("www.pngimg.com", "80", &host_info, &host_info_list);
if (status != 0) {
cout << "getaddrinfo error" << endl;
}
int socketfd;
socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype,
host_info_list->ai_protocol);
addrinfo *rp;
for (rp = host_info_list; rp != NULL; rp = rp->ai_next) {
socketfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (socketfd == -1) {
cout << "socket error" << endl;
}
if (connect(socketfd, rp->ai_addr, rp->ai_addrlen) != -1) {
break;
}
close(socketfd);
}
if (rp == NULL) {
cout << "Could not connect!" << endl;
exit(EXIT_FAILURE);
}
freeaddrinfo(host_info_list);
const char *msg =
"GET /upload/water_PNG3290.png HTTP/1.1\r\nhost: www.pngimg.com\r\nConnection: close\r\n\r\n";
status = send(socketfd, msg, strlen(msg), 0);
if (status == -1) {
cout << "error sending" << endl;
exit(EXIT_FAILURE);
}
getPicture(socketfd, 1024);
close(socketfd);
return 0;
}
catコマンドを使用してからの画像です: terminal above is picture from my code, below is picture from chromium "save as"
バイナリデータに 'strlen'を使用することはできません。 –
ありがとう、私はそれを変更しました。しかし、それは本当の問題ではないと思います。 – Jake
'char *'から 'std :: string'を構築すると、データの最初の0にも停止します。ヘッダーのバイト数を 'bReceived'から差し引いて残りのバッファーをファイルに書き込むことをお勧めします。 –