NEWS

[C#] Chia sẻ source code phần mềm Image Downloader tải hàng loạt hình ảnh từ danh sách link url

[C#] Chia sẻ source code phần mềm Image Downloader tải hàng loạt hình ảnh từ danh sách link url
Đăng bởi: Thảo Meo - Lượt xem: 36 11:44:44, 09/08/2025EBOOK

Xin chào các bạn, bài viết hôm nay mình chia sẻ các bạn tool dùng để tải hàng loạt hình ảnh từ list danh sách link mình đang có chỉ 1 cái click chuột.

[C#] Chia sẻ source code phần mềm Image Downloader tải hình ảnh hàng loạt

Giao diện demo ứng dụng:

phân mềm tải ảnh hàng loạt

Như hình, các bạn chỉ cần dán danh sách link vào và bấm nút tải về.

Có thể xem trước (preview) từng hình ảnh.

Dưới đây là video demo ứng dụng:



Source code C#:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Linq;

namespace ImageDownloader
{
    public partial class MainForm : Form
    {
        private ListBox listBoxUrls;
        private TextBox textBoxUrls;
        private TextBox textBoxOutputPath;
        private Button buttonBrowseOutput;
        private Button buttonAddUrls;
        private Button buttonRemoveUrl;
        private Button buttonDownloadAll;
        private Button buttonClearAll;
        private ProgressBar progressBar;
        private Label labelStatus;
        private PictureBox pictureBoxPreview;
        private Label labelPreview;
        private Panel panelPreview;
        private static readonly HttpClient httpClient = new HttpClient();

        public MainForm()
        {
            InitializeComponent();
            InitializeHttpClient();
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();

            // Form properties
            this.Text = "Image Downloader - https://laptrinhvb.net";
            this.Size = new Size(1000, 600);
            this.StartPosition = FormStartPosition.CenterScreen;
            this.FormBorderStyle = FormBorderStyle.Sizable;
            this.MinimumSize = new Size(800, 500);

            // URL input textbox (multiline for pasting multiple URLs)
            this.textBoxUrls = new TextBox
            {
                Location = new Point(12, 12),
                Size = new Size(450, 100),
                Multiline = true,
                ScrollBars = ScrollBars.Vertical,
               
            };

            // Add URLs button
            this.buttonAddUrls = new Button
            {
                Location = new Point(470, 12),
                Size = new Size(80, 30),
                Text = "Add URLs",
                UseVisualStyleBackColor = true
            };
            this.buttonAddUrls.Click += ButtonAddUrls_Click;

            // URLs ListBox
            this.listBoxUrls = new ListBox
            {
                Location = new Point(12, 120),
                Size = new Size(550, 200),
                SelectionMode = SelectionMode.MultiExtended
            };
            this.listBoxUrls.SelectedIndexChanged += ListBoxUrls_SelectedIndexChanged;
            this.listBoxUrls.KeyDown += ListBoxUrls_KeyDown;

            // Remove URL button
            this.buttonRemoveUrl = new Button
            {
                Location = new Point(12, 330),
                Size = new Size(100, 30),
                Text = "Remove Selected",
                UseVisualStyleBackColor = true
            };
            this.buttonRemoveUrl.Click += ButtonRemoveUrl_Click;

            // Clear all button
            this.buttonClearAll = new Button
            {
                Location = new Point(120, 330),
                Size = new Size(80, 30),
                Text = "Clear All",
                UseVisualStyleBackColor = true
            };
            this.buttonClearAll.Click += ButtonClearAll_Click;

            // Output path label
            Label labelOutput = new Label
            {
                Location = new Point(12, 375),
                Size = new Size(100, 20),
                Text = "Output Folder:"
            };

            // Output path textbox
            this.textBoxOutputPath = new TextBox
            {
                Location = new Point(12, 400),
                Size = new Size(450, 23),
                Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Downloaded_Images")
            };

            // Browse output button
            this.buttonBrowseOutput = new Button
            {
                Location = new Point(470, 400),
                Size = new Size(75, 23),
                Text = "Browse",
                UseVisualStyleBackColor = true
            };
            this.buttonBrowseOutput.Click += ButtonBrowseOutput_Click;

            // Download all button
            this.buttonDownloadAll = new Button
            {
                Location = new Point(12, 435),
                Size = new Size(120, 35),
                Text = "Download All",
                UseVisualStyleBackColor = true,
                BackColor = Color.LightGreen
            };
            this.buttonDownloadAll.Click += ButtonDownloadAll_Click;

            // Progress bar
            this.progressBar = new ProgressBar
            {
                Location = new Point(12, 485),
                Size = new Size(550, 23),
                Style = ProgressBarStyle.Continuous
            };

            // Status label
            this.labelStatus = new Label
            {
                Location = new Point(12, 520),
                Size = new Size(550, 40),
                Text = "Ready to download images...",
                AutoSize = false
            };

            // Preview Panel
            this.panelPreview = new Panel
            {
                Location = new Point(580, 12),
                Size = new Size(400, 548),
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = Color.WhiteSmoke
            };

            // Preview label
            this.labelPreview = new Label
            {
                Location = new Point(10, 10),
                Size = new Size(380, 20),
                Text = "Click on a URL to preview image",
                TextAlign = ContentAlignment.MiddleCenter,
                Font = new Font("Microsoft Sans Serif", 9, FontStyle.Bold)
            };

            // Picture box for preview
            this.pictureBoxPreview = new PictureBox
            {
                Location = new Point(10, 40),
                Size = new Size(380, 500),
                SizeMode = PictureBoxSizeMode.Zoom,
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = Color.White
            };

            // Add controls to preview panel
            this.panelPreview.Controls.AddRange(new Control[] {
                this.labelPreview,
                this.pictureBoxPreview
            });

            // Add controls to form
            this.Controls.AddRange(new Control[] {
                this.textBoxUrls,
                this.buttonAddUrls,
                this.listBoxUrls,
                this.buttonRemoveUrl,
                this.buttonClearAll,
                labelOutput,
                this.textBoxOutputPath,
                this.buttonBrowseOutput,
                this.buttonDownloadAll,
                this.progressBar,
                this.labelStatus,
                this.panelPreview
            });

            // Handle form resize
            this.Resize += MainForm_Resize;

            this.ResumeLayout();
        }

        private void MainForm_Resize(object sender, EventArgs e)
        {
            // Adjust preview panel position and size when form is resized
            int formWidth = this.ClientSize.Width;
            int formHeight = this.ClientSize.Height;

            // Adjust main controls width
            int mainControlsWidth = Math.Max(300, formWidth - 420);

            textBoxUrls.Width = mainControlsWidth - 120;
            listBoxUrls.Width = mainControlsWidth;
            textBoxOutputPath.Width = mainControlsWidth - 80;
            progressBar.Width = mainControlsWidth;
            labelStatus.Width = mainControlsWidth;

            // Adjust button positions
            buttonAddUrls.Left = textBoxUrls.Right + 10;
            buttonBrowseOutput.Left = textBoxOutputPath.Right + 10;

            // Adjust preview panel
            panelPreview.Left = mainControlsWidth + 20;
            panelPreview.Width = Math.Max(300, formWidth - mainControlsWidth - 40);
            panelPreview.Height = formHeight - 30;

            // Adjust preview controls
            labelPreview.Width = panelPreview.Width - 20;
            pictureBoxPreview.Width = panelPreview.Width - 20;
            pictureBoxPreview.Height = panelPreview.Height - 60;
        }

        private void InitializeHttpClient()
        {
            httpClient.DefaultRequestHeaders.Add("User-Agent",
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            httpClient.Timeout = TimeSpan.FromMinutes(5);
        }

        private void ButtonAddUrls_Click(object sender, EventArgs e)
        {
            string urlsText = textBoxUrls.Text.Trim();
            if (!string.IsNullOrEmpty(urlsText))
            {
                string[] urls = urlsText.Split(new char[] { '\n', '\r' },
                    StringSplitOptions.RemoveEmptyEntries);

                int addedCount = 0;
                int duplicateCount = 0;
                int invalidCount = 0;

                foreach (string url in urls)
                {
                    string trimmedUrl = url.Trim();
                    if (!string.IsNullOrEmpty(trimmedUrl))
                    {
                        if (IsValidImageUrl(trimmedUrl))
                        {
                            if (!listBoxUrls.Items.Contains(trimmedUrl))
                            {
                                listBoxUrls.Items.Add(trimmedUrl);
                                addedCount++;
                            }
                            else
                            {
                                duplicateCount++;
                            }
                        }
                        else
                        {
                            invalidCount++;
                        }
                    }
                }

                textBoxUrls.Clear();

                string statusMessage = $"Added {addedCount} URLs. Total: {listBoxUrls.Items.Count}";
                if (duplicateCount > 0)
                    statusMessage += $" (Skipped {duplicateCount} duplicates)";
                if (invalidCount > 0)
                    statusMessage += $" (Skipped {invalidCount} invalid URLs)";

                labelStatus.Text = statusMessage;

                if (invalidCount > 0)
                {
                    MessageBox.Show($"Skipped {invalidCount} invalid URLs. Only image URLs with extensions (jpg, jpeg, png, gif, bmp, webp) are accepted.",
                        "Invalid URLs", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
        }

        private async void ListBoxUrls_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBoxUrls.SelectedItem != null)
            {
                string selectedUrl = listBoxUrls.SelectedItem.ToString();
                await LoadPreviewImage(selectedUrl);
            }
            else
            {
                // Clear preview when no selection
                pictureBoxPreview.Image?.Dispose();
                pictureBoxPreview.Image = null;
                labelPreview.Text = "Click on a URL to preview image";
            }
        }

        private async Task LoadPreviewImage(string url)
        {
            try
            {
                labelPreview.Text = "Loading preview...";
                pictureBoxPreview.Image?.Dispose();
                pictureBoxPreview.Image = null;

                // Load image from URL
                byte[] imageBytes = await httpClient.GetByteArrayAsync(url);
                using (var ms = new MemoryStream(imageBytes))
                {
                    Image image = Image.FromStream(ms);
                    pictureBoxPreview.Image = new Bitmap(image); // Create a copy
                }

                // Update label with image info
                if (pictureBoxPreview.Image != null)
                {
                    string fileName = GetFileNameFromUrl(url);
                    labelPreview.Text = $"{fileName} ({pictureBoxPreview.Image.Width}x{pictureBoxPreview.Image.Height})";
                }
            }
            catch (Exception ex)
            {
                pictureBoxPreview.Image?.Dispose();
                pictureBoxPreview.Image = null;
                labelPreview.Text = $"Failed to load preview: {ex.Message}";
            }
        }

        private void ListBoxUrls_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                ButtonRemoveUrl_Click(sender, e);
            }
        }

        private void ButtonRemoveUrl_Click(object sender, EventArgs e)
        {
            if (listBoxUrls.SelectedItems.Count > 0)
            {
                var itemsToRemove = new List<object>();
                foreach (object item in listBoxUrls.SelectedItems)
                {
                    itemsToRemove.Add(item);
                }

                foreach (object item in itemsToRemove)
                {
                    listBoxUrls.Items.Remove(item);
                }

                labelStatus.Text = $"Removed {itemsToRemove.Count} URLs. Total: {listBoxUrls.Items.Count}";

                // Clear preview if no items selected
                if (listBoxUrls.SelectedItems.Count == 0)
                {
                    pictureBoxPreview.Image?.Dispose();
                    pictureBoxPreview.Image = null;
                    labelPreview.Text = "Click on a URL to preview image";
                }
            }
        }

        private void ButtonClearAll_Click(object sender, EventArgs e)
        {
            if (listBoxUrls.Items.Count > 0)
            {
                var result = MessageBox.Show("Are you sure you want to clear all URLs?",
                    "Clear All", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (result == DialogResult.Yes)
                {
                    listBoxUrls.Items.Clear();
                    labelStatus.Text = "All URLs cleared.";

                    // Clear preview
                    pictureBoxPreview.Image?.Dispose();
                    pictureBoxPreview.Image = null;
                    labelPreview.Text = "Click on a URL to preview image";
                }
            }
        }

        private void ButtonBrowseOutput_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog folderDialog = new FolderBrowserDialog())
            {
                folderDialog.Description = "Select output folder for downloaded images";
                folderDialog.SelectedPath = textBoxOutputPath.Text;

                if (folderDialog.ShowDialog() == DialogResult.OK)
                {
                    textBoxOutputPath.Text = folderDialog.SelectedPath;
                }
            }
        }

        private async void ButtonDownloadAll_Click(object sender, EventArgs e)
        {
            if (listBoxUrls.Items.Count == 0)
            {
                MessageBox.Show("No URLs to download!", "No URLs",
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            string outputPath = textBoxOutputPath.Text.Trim();
            if (string.IsNullOrEmpty(outputPath))
            {
                MessageBox.Show("Please select an output folder!", "No Output Folder",
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            try
            {
                // Create output directory if it doesn't exist
                if (!Directory.Exists(outputPath))
                {
                    Directory.CreateDirectory(outputPath);
                }

                // Disable controls during download
                SetControlsEnabled(false);

                progressBar.Maximum = listBoxUrls.Items.Count;
                progressBar.Value = 0;

                int successCount = 0;
                int failCount = 0;

                for (int i = 0; i < listBoxUrls.Items.Count; i++)
                {
                    string url = listBoxUrls.Items[i].ToString();
                    labelStatus.Text = $"Downloading {i + 1} of {listBoxUrls.Items.Count}: {Path.GetFileName(url)}";

                    try
                    {
                        await DownloadImage(url, outputPath);
                        successCount++;
                    }
                    catch (Exception ex)
                    {
                        failCount++;
                        // Log error but continue with other downloads
                        Console.WriteLine($"Failed to download {url}: {ex.Message}");
                    }

                    progressBar.Value = i + 1;
                    Application.DoEvents(); // Update UI
                }

                labelStatus.Text = $"Download completed! Success: {successCount}, Failed: {failCount}";

                if (successCount > 0)
                {
                    var result = MessageBox.Show($"Download completed!\n\nSuccess: {successCount}\nFailed: {failCount}\n\nOpen output folder?",
                        "Download Complete", MessageBoxButtons.YesNo, MessageBoxIcon.Information);

                    if (result == DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start("explorer.exe", outputPath);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error during download: {ex.Message}", "Download Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                labelStatus.Text = "Download failed!";
            }
            finally
            {
                SetControlsEnabled(true);
                progressBar.Value = 0;
            }
        }

        private async Task DownloadImage(string url, string outputPath)
        {
            try
            {
                byte[] imageBytes = await httpClient.GetByteArrayAsync(url);

                // Generate filename from URL
                string fileName = GetFileNameFromUrl(url);
                string fullPath = Path.Combine(outputPath, fileName);

                // Handle duplicate filenames
                int counter = 1;
                string originalFileName = Path.GetFileNameWithoutExtension(fileName);
                string extension = Path.GetExtension(fileName);

                while (File.Exists(fullPath))
                {
                    fileName = $"{originalFileName}_{counter}{extension}";
                    fullPath = Path.Combine(outputPath, fileName);
                    counter++;
                }

                await Task.Run(() => File.WriteAllBytes(fullPath, imageBytes));
            }
            catch (HttpRequestException ex)
            {
                throw new Exception($"Network error: {ex.Message}");
            }
            catch (TaskCanceledException)
            {
                throw new Exception("Download timeout");
            }
            catch (Exception ex)
            {
                throw new Exception($"Download failed: {ex.Message}");
            }
        }

        private string GetFileNameFromUrl(string url)
        {
            try
            {
                Uri uri = new Uri(url);
                string fileName = Path.GetFileName(uri.LocalPath);

                // If no filename in URL, generate one
                if (string.IsNullOrEmpty(fileName) || !fileName.Contains("."))
                {
                    string extension = GetImageExtensionFromUrl(url);
                    fileName = $"image_{DateTime.Now:yyyyMMdd_HHmmss}_{Guid.NewGuid().ToString("N").Substring(0, 8)}{extension}";
                }

                // Remove invalid characters
                string invalidChars = new string(Path.GetInvalidFileNameChars());
                foreach (char c in invalidChars)
                {
                    fileName = fileName.Replace(c, '_');
                }

                return fileName;
            }
            catch
            {
                return $"image_{DateTime.Now:yyyyMMdd_HHmmss}.jpg";
            }
        }

        private string GetImageExtensionFromUrl(string url)
        {
            string[] extensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp" };

            foreach (string ext in extensions)
            {
                if (url.ToLower().Contains(ext))
                    return ext;
            }

            return ".jpg"; // Default extension
        }

        private bool IsValidImageUrl(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
                return false;

            try
            {
                Uri uri = new Uri(url);
                if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
                    return false;

                string[] validExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp" };
                string lowerUrl = url.ToLower();

                return validExtensions.Any(ext => lowerUrl.Contains(ext)) ||
                       lowerUrl.Contains("image") ||
                       lowerUrl.Contains("photo") ||
                       lowerUrl.Contains("pic");
            }
            catch
            {
                return false;
            }
        }

        private void SetControlsEnabled(bool enabled)
        {
            buttonAddUrls.Enabled = enabled;
            buttonRemoveUrl.Enabled = enabled;
            buttonClearAll.Enabled = enabled;
            buttonDownloadAll.Enabled = enabled;
            buttonBrowseOutput.Enabled = enabled;
            textBoxUrls.Enabled = enabled;
            listBoxUrls.Enabled = enabled;
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            // Dispose preview image
            pictureBoxPreview.Image?.Dispose();
            httpClient?.Dispose();
            base.OnFormClosed(e);
        }
    }

    // Program entry point
    
}

Thanks for watching!

Download source

THÔNG TIN TÁC GIẢ

BÀI VIẾT LIÊN QUAN

[C#] Chia sẻ source code phần mềm Image Downloader tải hàng loạt hình ảnh từ danh sách link url
Đăng bởi: Thảo Meo - Lượt xem: 36 11:44:44, 09/08/2025EBOOK