0% found this document useful (0 votes)
9 views3 pages

Web Downloader C

Uploaded by

txongoku
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views3 pages

Web Downloader C

Uploaded by

txongoku
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 3

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <curl/curl.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

#define MAX_THREADS 10
#define MAX_URL_LENGTH 2048
#define MAX_FILENAME_LENGTH 256

typedef struct {
char url[MAX_URL_LENGTH];
char filename[MAX_FILENAME_LENGTH];
double progress;
pthread_mutex_t mutex;
} DownloadInfo;

DownloadInfo downloads[MAX_THREADS];
int active_downloads = 0;
pthread_mutex_t console_mutex = PTHREAD_MUTEX_INITIALIZER;

size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {


return fwrite(ptr, size, nmemb, stream);
}

int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal,


double ulnow) {
DownloadInfo *info = (DownloadInfo *)clientp;
pthread_mutex_lock(&info->mutex);
info->progress = (dltotal > 0) ? (dlnow / dltotal * 100) : 0;
pthread_mutex_unlock(&info->mutex);
return 0;
}

void *download_thread(void *arg) {


DownloadInfo *info = (DownloadInfo *)arg;
CURL *curl;
FILE *fp;
CURLcode res;

curl = curl_easy_init();
if (curl) {
fp = fopen(info->filename, "wb");
curl_easy_setopt(curl, CURLOPT_URL, info->url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, info);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
}

pthread_mutex_lock(&console_mutex);
active_downloads--;
pthread_mutex_unlock(&console_mutex);

return NULL;
}

void print_progress() {
pthread_mutex_lock(&console_mutex);
printf("\033[2J\033[H"); // Clear screen and move cursor to top-left
for (int i = 0; i < MAX_THREADS; i++) {
if (downloads[i].filename[0] != '\0') {
printf("%s: %.2f%%\n", downloads[i].filename, downloads[i].progress);
}
}
pthread_mutex_unlock(&console_mutex);
}

int main(int argc, char *argv[]) {


if (argc != 2) {
fprintf(stderr, "Uso: %s <URL>\n", argv[0]);
return 1;
}

CURL *curl = curl_easy_init();


if (!curl) {
fprintf(stderr, "Error al inicializar cURL\n");
return 1;
}

// Crear carpeta con la fecha actual


time_t t = time(NULL);
struct tm *tm = localtime(&t);
char foldername[20];
strftime(foldername, sizeof(foldername), "%Y-%m-%d--%H%M%S", tm);
mkdir(foldername, 0777);

// Obtener lista de archivos


char *url = argv[1];
char *buffer = NULL;
size_t size = 0;
FILE *stream = open_memstream(&buffer, &size);

curl_easy_setopt(curl, CURLOPT_URL, url);


curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, stream);
CURLcode res = curl_easy_perform(curl);
fclose(stream);

if (res != CURLE_OK) {
fprintf(stderr, "Error al obtener la lista de archivos: %s\n",
curl_easy_strerror(res));
free(buffer);
curl_easy_cleanup(curl);
return 1;
}

// Procesar la lista de archivos (esto es una simplificación, necesitarías un


parser HTML adecuado)
char *line = strtok(buffer, "\n");
pthread_t threads[MAX_THREADS];
int thread_count = 0;

while (line != NULL) {


char *href = strstr(line, "href=\"");
if (href) {
href += 6;
char *end = strchr(href, '"');
if (end) {
*end = '\0';
if (href[0] != '/' && strstr(href, "://") == NULL) {
char full_url[MAX_URL_LENGTH];
snprintf(full_url, sizeof(full_url), "%s/%s", url, href);

while (active_downloads >= MAX_THREADS) {


print_progress();
sleep(1);
}

pthread_mutex_lock(&console_mutex);
int idx = thread_count % MAX_THREADS;
active_downloads++;
strcpy(downloads[idx].url, full_url);
snprintf(downloads[idx].filename,
sizeof(downloads[idx].filename), "%s/%s", foldername, href);
downloads[idx].progress = 0;
pthread_mutex_init(&downloads[idx].mutex, NULL);
pthread_create(&threads[thread_count], NULL, download_thread,
&downloads[idx]);
thread_count++;
pthread_mutex_unlock(&console_mutex);
}
}
}
line = strtok(NULL, "\n");
}

free(buffer);
curl_easy_cleanup(curl);

// Esperar a que terminen todas las descargas


while (active_downloads > 0) {
print_progress();
sleep(1);
}

for (int i = 0; i < thread_count; i++) {


pthread_join(threads[i], NULL);
}

printf("Todas las descargas han sido completadas.\n");


return 0;
}

You might also like