C# WinFrom+AspNetCore WebApi实现大文件下载与上传

2024-02-14 06:04

本文主要是介绍C# WinFrom+AspNetCore WebApi实现大文件下载与上传,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

客户端UI:

服务端WebApi:

客户端代码:

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><appSettings><add key="WebApi" value="https://localhost:7285"/><add key="SavePath" value="E:\Down"/><add key="DownFileName" value="win11x64.esd"/><add key="UploadFileName" value="win11x64.esd"/></appSettings>
</configuration>

自定义进度条:

CustomProgressBar.cs(长方形)

using System;
using System.Windows.Forms;
using System.Drawing;namespace FileUploadAndDown
{public class CustomProgressBar : ProgressBar{// 添加一个属性来存储速率文本public string RateText { get; set; } = "0 KB/s";public CustomProgressBar(){// 设置样式以允许重绘。this.SetStyle(ControlStyles.UserPaint, true);}protected override void OnPaint(PaintEventArgs e){Rectangle rect = this.ClientRectangle;Graphics g = e.Graphics;ProgressBarRenderer.DrawHorizontalBar(g, rect);rect.Inflate(-3, -3); // 减小大小以适应边界if (this.Value > 0){Rectangle clip = new Rectangle(rect.X, rect.Y, (int)Math.Round(((float)this.Value / this.Maximum) * rect.Width), rect.Height);g.FillRectangle(Brushes.GreenYellow, clip);}string text = this.Value.ToString() + "%";using (Font f = new Font(FontFamily.GenericSansSerif, 10)){SizeF len = g.MeasureString(text, f);Point location = new Point((int)((rect.Width / 2) - (len.Width / 2)), (int)((rect.Height / 2) - (len.Height / 2)));g.DrawString(text, f, Brushes.Black, location);// 绘制速率文本SizeF rateLen = g.MeasureString(RateText, f);Point rateLocation = new Point(rect.Right - (int)rateLen.Width - 5, (int)((rect.Height / 2) - (rateLen.Height / 2)));g.DrawString(RateText, f, Brushes.Black, rateLocation);}}}
}

自定义圆型进度条:

CircularProgressBar.cs

using System;
using System.Drawing;
using System.Windows.Forms;namespace FileUploadAndDown
{public class CircularProgressBar : UserControl{private int progress = 0;private int max = 100;public int Progress{get { return progress; }set{progress = value;this.Invalidate(); // 通知控件需要重绘}}public int Maximum{get { return max; }set{max = value;this.Invalidate(); // 通知控件需要重绘}}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);Graphics g = e.Graphics;g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;// 绘制外圈g.DrawEllipse(Pens.Black, 0, 0, this.Width - 1, this.Height - 1);// 计算进度float sweepAngle = 360f * progress / max;// 绘制进度using (Brush brush = new SolidBrush(Color.Blue)){g.FillPie(brush, 0, 0, this.Width, this.Height, -90, sweepAngle);}// 绘制中心覆盖圆,形成环形进度条int coverSize = 20; // 中心圆的大小,可以根据需要调整using (Brush brush = new SolidBrush(this.BackColor)){g.FillEllipse(brush, (this.Width - coverSize) / 2, (this.Height - coverSize) / 2, coverSize, coverSize);}}}
}

HttpContent.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Threading.Tasks;namespace FileUploadAndDown
{public class ProgressableStreamContent : HttpContent{private readonly HttpContent content;private readonly int bufferSize = 4096;private readonly Action<long, long> progress;public ProgressableStreamContent(HttpContent content, Action<long, long> progress){this.content = content ?? throw new ArgumentNullException(nameof(content));this.progress = progress ?? throw new ArgumentNullException(nameof(progress));foreach (var header in content.Headers){this.Headers.TryAddWithoutValidation(header.Key, header.Value);}}protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context){var buffer = new byte[bufferSize];TryComputeLength(out long size);var uploaded = 0L;using (var contentStream = await content.ReadAsStreamAsync()){var read = 0;while ((read = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0){await stream.WriteAsync(buffer, 0, read);uploaded += read;progress(uploaded, size);}}}protected override bool TryComputeLength(out long length){length = content.Headers.ContentLength ?? -1;return length != -1;}}
}

ServerResponse.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace FileUploadAndDown
{public class ServerResponse{public int Code { get; set; }public string Message { get; set; }public FileListData Data { get; set; }}public class FileListData{public List<string> Files { get; set; }}}

MainWinFrm.cs

using System;
using System.IO;
using System.Net.Http;
using System.Windows.Forms;
using System.Threading.Tasks;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Configuration;
using static System.Net.WebRequestMethods;namespace FileUploadAndDown
{public partial class MainWinFrm : Form{private HttpClient _httpClient = new HttpClient();public List<string> fileInfos = new List<string>();/// <summary>/// 保存文件路径/// </summary>public string? SavePath { get; set; }/// <summary>/// 下载文件名称/// </summary>public string? DownFileName { get; set; }/// <summary>/// 上传文件名称/// </summary>public string? UploadFileName { get; set; }/// <summary>/// WebApi接口/// </summary>public string? WebApi { get; set; }public MainWinFrm(){InitializeComponent();//读取配置信息this.WebApi = ConfigurationManager.AppSettings["WebApi"]!;this.SavePath = ConfigurationManager.AppSettings["SavePath"]!;this.DownFileName = ConfigurationManager.AppSettings["DownFileName"]!;this.UploadFileName = ConfigurationManager.AppSettings["UploadFileName"]!;_httpClient = new HttpClient{Timeout = TimeSpan.FromMinutes(10) // 设置超时时间为10分钟};// 初始化进度条InitializeUI();}private void InitializeUI(){// 设置进度条属性progressBar.Minimum = 0;progressBar.Maximum = 100;progressBar.Value = 0;FetchDownloadableFiles();//获取所有文件}#region 上传文件private async void btn_Upload_Click(object sender, EventArgs e){OpenFileDialog openFileDialog = new OpenFileDialog();if (openFileDialog.ShowDialog() == DialogResult.OK){string filePath = openFileDialog.FileName;await UploadFile(filePath);}}#endregion#region 下载private async void btn_Dwon_Click(object sender, EventArgs e){// 这里可以使用fileInfos列表让用户选择要下载的文件,例如通过一个下拉菜单if (fileInfos == null || fileInfos.Count == 0){MessageBox.Show("No files available for download.");return;}string fileName = fileInfos[0]; // 假设用户选择了列表中的第一个文件await DownloadFile(fileName);}#endregion#region 上传/// <summary>/// 上传文件/// </summary>/// <param name="filePath">上传文件路径及名称</param>/// <returns></returns>private async Task UploadFile(string filePath){var fileInfo = new FileInfo(filePath);var fileContent = new StreamContent(System.IO.File.OpenRead(filePath));var content = new MultipartFormDataContent{{ fileContent, "file", fileInfo.Name }};var lastUpdateTime = DateTime.Now; // 用于跟踪上次更新时间var lastReportedProgress = -1; // 用于跟踪上次报告的进度long lastUploadedBytes = 0; // 上次上传的字节数var progressContent = new ProgressableStreamContent(content, (uploaded, total) =>{var now = DateTime.Now;var timeSpan = now - lastUpdateTime;if (timeSpan.TotalSeconds >= 1) // 每秒更新一次速率{var rate = (uploaded - lastUploadedBytes) / timeSpan.TotalSeconds / 1024; // 速率 KB/slastUpdateTime = now;lastUploadedBytes = uploaded;var progressPercentage = (int)((uploaded * 100) / total);if (Math.Abs(progressPercentage - lastReportedProgress) >= 1){lastReportedProgress = progressPercentage;Invoke((MethodInvoker)delegate{progressBar.Value = progressPercentage;progressBar.RateText = $"{rate:0.00} KB/s"; // 更新速率信息lblProgress.Text = $"{progressPercentage}%"; // 更新进度标签});}}});var response = await _httpClient.PostAsync($@"{this.WebApi}/Files/upload", progressContent);if (response.IsSuccessStatusCode){Invoke((MethodInvoker)delegate{MessageBox.Show("File uploaded successfully.");});}else{Invoke((MethodInvoker)delegate{MessageBox.Show($"Upload failed: {response.ReasonPhrase}");});}}#endregion#region 下载/// <summary>/// 下载文件/// </summary>/// <param name="fileName">下载文件名称</param>/// <param name="savePath">下载文件保存路径</param>/// <returns></returns>private async Task DownloadFile(string fileName){var response = await _httpClient.GetAsync($"{this.WebApi}/Files/download/{fileName}", HttpCompletionOption.ResponseHeadersRead);if (response.IsSuccessStatusCode){var saveFilePath = Path.Combine(SavePath, fileName);using (var stream = await response.Content.ReadAsStreamAsync())using (var fileStream = new FileStream(saveFilePath, FileMode.Create, FileAccess.Write, FileShare.None)){var totalRead = 0L;var totalReadBytes = response.Content.Headers.ContentLength ?? 0;var buffer = new byte[4096];var isMoreToRead = true;var lastReportedProgress = -1; // 用于跟踪上次报告的进度var lastUpdateTime = DateTime.Now; // 用于跟踪上次更新时间long lastDownloadedBytes = 0; // 上次下载的字节数do{var read = await stream.ReadAsync(buffer, 0, buffer.Length);if (read == 0){isMoreToRead = false;}else{await fileStream.WriteAsync(buffer, 0, read);totalRead += read;var progress = (int)((totalRead * 100) / totalReadBytes);var now = DateTime.Now;var timeSpan = now - lastUpdateTime;if (timeSpan.TotalSeconds >= 1) // 每秒更新一次速率{var rate = (totalRead - lastDownloadedBytes) / timeSpan.TotalSeconds / 1024; // 速率 KB/slastUpdateTime = now;lastDownloadedBytes = totalRead;// 仅当进度有显著变化时才更新 UIif (Math.Abs(progress - lastReportedProgress) >= 1) // 这里的 1 表示至少有 1% 的变化{lastReportedProgress = progress;Invoke((MethodInvoker)delegate{progressBar.Value = progress;progressBar.RateText = $"{rate:0.00} KB/s"; // 更新速率信息lblProgress.Text = $"{progress}%"; // 更新进度标签});}}}} while (isMoreToRead);}Invoke((MethodInvoker)delegate{MessageBox.Show($"File downloaded successfully and saved as {saveFilePath}.");});}else{Invoke((MethodInvoker)delegate{MessageBox.Show($"Download failed: {response.ReasonPhrase}");});}}#endregion// 新增方法:获取服务器上可下载的文件列表#region 获取所有文件信息private async void FetchDownloadableFiles(){try{var response = await _httpClient.GetAsync($"{this.WebApi}/Files/list");if (response.IsSuccessStatusCode){var jsonString = await response.Content.ReadAsStringAsync();var serverResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<ServerResponse>(jsonString);if (serverResponse != null && serverResponse.Data != null && serverResponse.Data.Files != null){this.fileInfos = serverResponse.Data.Files;// 更新UI,例如使用ComboBox或ListBox展示文件列表// 注意:此处更新UI的代码应该在UI线程上执行,可能需要使用Invoke或BeginInvoke方法}}else{MessageBox.Show("Failed to fetch files list.");}}catch (Exception ex){MessageBox.Show($"Error fetching files list: {ex.Message}");}}#endregion}
}

MainWinFrm.Designer.cs

namespace FileUploadAndDown
{partial class MainWinFrm{/// <summary>///  Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>///  Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>///  Required method for Designer support - do not modify///  the contents of this method with the code editor./// </summary>private void InitializeComponent(){splitContainer1 = new SplitContainer();progressBar = new CustomProgressBar();lblProgress = new Label();btn_Dwon = new Button();btn_Upload = new Button();label3 = new Label();label2 = new Label();label1 = new Label();circularProgressBar1 = new CircularProgressBar();((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();splitContainer1.Panel1.SuspendLayout();splitContainer1.Panel2.SuspendLayout();splitContainer1.SuspendLayout();SuspendLayout();// // splitContainer1// splitContainer1.Dock = DockStyle.Fill;splitContainer1.Location = new Point(0, 0);splitContainer1.Margin = new Padding(4);splitContainer1.Name = "splitContainer1";splitContainer1.Orientation = Orientation.Horizontal;// // splitContainer1.Panel1// splitContainer1.Panel1.Controls.Add(progressBar);splitContainer1.Panel1.Controls.Add(lblProgress);// // splitContainer1.Panel2// splitContainer1.Panel2.Controls.Add(circularProgressBar1);splitContainer1.Panel2.Controls.Add(btn_Dwon);splitContainer1.Panel2.Controls.Add(btn_Upload);splitContainer1.Panel2.Controls.Add(label3);splitContainer1.Panel2.Controls.Add(label2);splitContainer1.Panel2.Controls.Add(label1);splitContainer1.Size = new Size(975, 135);splitContainer1.SplitterDistance = 47;splitContainer1.SplitterWidth = 6;splitContainer1.TabIndex = 0;// // progressBar// progressBar.Dock = DockStyle.Fill;progressBar.Location = new Point(0, 0);progressBar.Name = "progressBar";progressBar.RateText = "0 KB/s";progressBar.Size = new Size(975, 47);progressBar.TabIndex = 2;// // lblProgress// lblProgress.AutoSize = true;lblProgress.BackColor = Color.Transparent;lblProgress.Location = new Point(494, 16);lblProgress.Name = "lblProgress";lblProgress.Size = new Size(0, 21);lblProgress.TabIndex = 1;lblProgress.TextAlign = ContentAlignment.MiddleCenter;// // btn_Dwon// btn_Dwon.BackColor = Color.PeachPuff;btn_Dwon.Dock = DockStyle.Bottom;btn_Dwon.Location = new Point(385, 47);btn_Dwon.Name = "btn_Dwon";btn_Dwon.Size = new Size(205, 35);btn_Dwon.TabIndex = 4;btn_Dwon.Text = "下载(&D)";btn_Dwon.UseVisualStyleBackColor = false;btn_Dwon.Click += btn_Dwon_Click;// // btn_Upload// btn_Upload.BackColor = Color.PeachPuff;btn_Upload.Dock = DockStyle.Top;btn_Upload.FlatAppearance.BorderSize = 0;btn_Upload.FlatStyle = FlatStyle.Flat;btn_Upload.Location = new Point(385, 0);btn_Upload.Name = "btn_Upload";btn_Upload.Size = new Size(205, 32);btn_Upload.TabIndex = 3;btn_Upload.Text = "上传(&U)";btn_Upload.UseVisualStyleBackColor = false;btn_Upload.Click += btn_Upload_Click;// // label3// label3.Dock = DockStyle.Fill;label3.Location = new Point(385, 0);label3.Name = "label3";label3.Size = new Size(205, 82);label3.TabIndex = 2;label3.Text = "label3";// // label2// label2.Dock = DockStyle.Right;label2.Location = new Point(590, 0);label2.Name = "label2";label2.Size = new Size(385, 82);label2.TabIndex = 1;// // label1// label1.Dock = DockStyle.Left;label1.Location = new Point(0, 0);label1.Name = "label1";label1.Size = new Size(385, 82);label1.TabIndex = 0;// // circularProgressBar1// circularProgressBar1.Location = new Point(114, 15);circularProgressBar1.Maximum = 100;circularProgressBar1.Name = "circularProgressBar1";circularProgressBar1.Progress = 0;circularProgressBar1.Size = new Size(57, 55);circularProgressBar1.TabIndex = 5;// // MainWinFrm// AutoScaleDimensions = new SizeF(10F, 21F);AutoScaleMode = AutoScaleMode.Font;ClientSize = new Size(975, 135);Controls.Add(splitContainer1);Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Regular, GraphicsUnit.Point);Margin = new Padding(4);Name = "MainWinFrm";StartPosition = FormStartPosition.CenterScreen;Text = "Form1";splitContainer1.Panel1.ResumeLayout(false);splitContainer1.Panel1.PerformLayout();splitContainer1.Panel2.ResumeLayout(false);((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit();splitContainer1.ResumeLayout(false);ResumeLayout(false);}#endregionprivate SplitContainer splitContainer1;private Label label1;private Button btn_Dwon;private Button btn_Upload;private Label label3;private Label label2;private Label lblProgress;private CustomProgressBar progressBar;private CircularProgressBar circularProgressBar1;}
}

服务端:

FilesController.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;namespace LargeFileHandling.Controllers
{[ApiController][Route("[controller]")]public class FilesController : ControllerBase{private readonly string _uploadFolderPath;public FilesController(FileStorageSettings fileStorageSettings){_uploadFolderPath = fileStorageSettings.UploadFolderPath;// Ensure the upload folder existsif (!Directory.Exists(_uploadFolderPath)){Directory.CreateDirectory(_uploadFolderPath);}}// Upload large file[HttpPost("upload")]public async Task<IActionResult> UploadLargeFile(IFormFile file){if (file == null || file.Length == 0){return BadRequest(new { code = 400, message = "Upload failed. No file provided.", data = new { } });}var filename = Path.GetFileName(file.FileName);var filePath = Path.Combine(_uploadFolderPath, filename);await using (var stream = System.IO.File.Create(filePath)){await file.CopyToAsync(stream);}return Ok(new { code = 200, message = "File uploaded successfully.", data = new { filePath } });}// Check if file exists and return JSON response[HttpGet("exists/{fileName}")]public IActionResult CheckFileExists(string fileName){var filePath = Path.Combine(_uploadFolderPath, fileName);if (System.IO.File.Exists(filePath)){return Ok(new { code = 200, message = "File exists.", data = new { filePath } });}else{return NotFound(new { code = 404, message = "File not found.", data = new { } });}}// Actual file download operation[HttpGet("download/{fileName}")]public IActionResult DownloadLargeFile(string fileName){var filePath = Path.Combine(_uploadFolderPath, fileName);if (!System.IO.File.Exists(filePath)){return NotFound(new { code = 404, message = "File not found.", data = new { } });}var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);return new FileStreamResult(stream, "application/octet-stream"){FileDownloadName = fileName};}// Modified method to list downloadable files including files in subdirectories[HttpGet("list")]public IActionResult ListDownloadableFiles(){if (!Directory.Exists(_uploadFolderPath)){return NotFound(new { code = 404, message = "Upload folder not found.", data = new { } });}var files = Directory.GetFiles(_uploadFolderPath, "*.*", SearchOption.AllDirectories).Select(file => file.Replace(_uploadFolderPath, "").TrimStart(Path.DirectorySeparatorChar)).ToList();return Ok(new { code = 200, message = "File list retrieved successfully.", data = new { files } });}}
}

appsettings.json

{"FileStorageSettings": {"UploadFolderPath": "F:\\Down"},"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*"
}

FileStorageSettings.cs

namespace LargeFileHandling
{public class FileStorageSettings{public string UploadFolderPath { get; set; }}
}

Program.cs

using LargeFileHandling;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Options;var builder = WebApplication.CreateBuilder(args);// 配置 Kestrel 服务器以允许大文件上传
builder.WebHost.ConfigureKestrel(serverOptions =>
{serverOptions.Limits.MaxRequestBodySize = 10L * 1024 * 1024 * 1024; // 10GB
});// 配置 FormOptions
builder.Services.Configure<FormOptions>(options =>
{options.MultipartBodyLengthLimit = 10L * 1024 * 1024 * 1024; // 10GB
});// 绑定文件存储配置并注册为单例服务
builder.Services.Configure<FileStorageSettings>(builder.Configuration.GetSection("FileStorageSettings"));
builder.Services.AddSingleton(resolver =>resolver.GetRequiredService<IOptions<FileStorageSettings>>().Value);// 其他服务和配置...
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();var app = builder.Build();// 应用的其余配置...
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();app.Run();

WeatherForecast.cs

namespace LargeFileHandling
{public class WeatherForecast{public DateTime Date { get; set; }public int TemperatureC { get; set; }public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);public string? Summary { get; set; }}
}

这篇关于C# WinFrom+AspNetCore WebApi实现大文件下载与上传的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/707685

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("