http.c: skip memory storage when download files
don't need to store the http data in memory when downloading files, write to disk directly.
This commit is contained in:
parent
3aea2adbc6
commit
c1a7c9671d
1 changed files with 29 additions and 39 deletions
68
http.c
68
http.c
|
|
@ -48,29 +48,18 @@ static char* strnstrr(const char *str, const char *needle, size_t size) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* url_filename(const char *url) {
|
static const char* url_filename(const char *url) {
|
||||||
|
|
||||||
const char *start = url;
|
const char *start = url;
|
||||||
char *name = NULL;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
for(; *url; url++) {
|
for(; *url; url++) {
|
||||||
if (*url != '/')
|
if (*url != '/')
|
||||||
continue;
|
continue;
|
||||||
if (*(url+1)) {
|
if (*(url+1) == 0)
|
||||||
start = url+1;
|
|
||||||
} else {
|
|
||||||
url--;
|
|
||||||
break;
|
break;
|
||||||
}
|
start = url + 1;
|
||||||
}
|
}
|
||||||
size = url - start;
|
return start;
|
||||||
if (size) {
|
|
||||||
name = malloc(size + 1);
|
|
||||||
memcpy(name, start, size + 1);
|
|
||||||
name[size+1] = '\0';
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HDR_CONDISP "Content-Disposition:"
|
#define HDR_CONDISP "Content-Disposition:"
|
||||||
|
|
@ -164,21 +153,25 @@ error:
|
||||||
|
|
||||||
int http_download_file(const char *url, const char *dir) {
|
int http_download_file(const char *url, const char *dir) {
|
||||||
|
|
||||||
int fd, err;
|
int err;
|
||||||
char *filename = NULL;
|
CURL *handle = NULL;
|
||||||
char path[4096];
|
|
||||||
CURL *handle;
|
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
struct http_data *data = malloc(sizeof(struct http_data));
|
FILE *fd;
|
||||||
|
char tmpfile[4096], *filename = NULL;
|
||||||
|
|
||||||
data->block = NULL;
|
/* Construct an filename from url. */
|
||||||
data->len = 0;
|
snprintf(tmpfile, sizeof(tmpfile), "%s/%s", dir, url_filename(url));
|
||||||
|
|
||||||
|
fd = fopen(tmpfile, "w");
|
||||||
|
if (!fd)
|
||||||
|
goto error;
|
||||||
|
|
||||||
handle = setup_connection(url);
|
handle = setup_connection(url);
|
||||||
|
|
||||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_cb);
|
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, fwrite);
|
||||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, data);
|
curl_easy_setopt(handle, CURLOPT_WRITEDATA, fd);
|
||||||
|
|
||||||
|
/* try look for the real filename in the http header */
|
||||||
curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, hdr_fname_cb);
|
curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, hdr_fname_cb);
|
||||||
curl_easy_setopt(handle, CURLOPT_HEADERDATA, &filename);
|
curl_easy_setopt(handle, CURLOPT_HEADERDATA, &filename);
|
||||||
|
|
||||||
|
|
@ -189,22 +182,19 @@ int http_download_file(const char *url, const char *dir) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filename) {
|
if (filename) {
|
||||||
filename = url_filename(url);
|
/* found the real file in http header.
|
||||||
|
move the old file. */
|
||||||
|
char realfile[4096];
|
||||||
|
|
||||||
|
snprintf(realfile, sizeof(realfile), "%s/%s", dir, filename);
|
||||||
|
if (rename(tmpfile, realfile) < 0)
|
||||||
|
goto error;
|
||||||
|
free(filename);
|
||||||
|
} else {
|
||||||
|
fclose(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now, write to file */
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", dir, filename);
|
|
||||||
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0644);
|
|
||||||
if (fd < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
write(fd, data->block, data->len);
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
free(filename);
|
|
||||||
http_free(data);
|
|
||||||
curl_easy_cleanup(handle);
|
curl_easy_cleanup(handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -212,7 +202,7 @@ error:
|
||||||
err = errno;
|
err = errno;
|
||||||
if (filename)
|
if (filename)
|
||||||
free(filename);
|
free(filename);
|
||||||
http_free(data);
|
fclose(fd);
|
||||||
curl_easy_cleanup(handle);
|
curl_easy_cleanup(handle);
|
||||||
errno = err;
|
errno = err;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
Reference in a new issue