- [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#] Chụp hình và quay video từ camera trên winform
- [C#] Chia sẽ full source code tách file Pdf thành nhiều file với các tùy chọn
- Giới thiệu về Stock Tracker Widget - Công cụ theo dõi cổ phiếu và cảnh báo giá tăng giảm bằng C# và WPF
- [VB.NET] Chia sẻ công cụ nhập số tiền tự động định dạng tiền tệ Việt Nam
- [VB.NET] Hướng dẫn fill dữ liệu từ winform vào Microsoft word
- [VB.NET] Hướng dẫn chọn nhiều dòng trên Datagridview
- Hướng Dẫn Đăng Nhập Nhiều Tài Khoản Zalo Trên Máy Tính Cực Kỳ Đơn Giản
- [C#] Chia sẻ source code phần mềm đếm số trang tập tin file PDF
- [C#] Cách Sử Dụng DeviceId trong C# Để Tạo Khóa Cho Ứng Dụng
- [SQLSERVER] Loại bỏ Restricted User trên database MSSQL
- [C#] Hướng dẫn tạo mã QRcode Style trên winform
- [C#] Hướng dẫn sử dụng temp mail service api trên winform
- [C#] Hướng dẫn tạo mã thanh toán VietQR Pay không sử dụng API trên winform
- [C#] Hướng Dẫn Tạo Windows Service Đơn Giản Bằng Topshelf
- [C#] Chia sẻ source code đọc dữ liệu từ Google Sheet trên winform
- [C#] Chia sẻ source code tạo mã QR MOMO đa năng Winform
- [C#] Chia sẻ source code phần mềm lên lịch tự động chạy ứng dụng Scheduler Task Winform
- [C#] Hướng dẫn download file từ Minio Server Winform
- [C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
[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
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:
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