Blazor Server中Quill编辑器插入图片的存储方案求助
Blazor Server 中 Quill 编辑器多图上传解决方案
问题分析
你当前已实现Quill编辑器文本内容的SQL存储与读取,但插入的图片无法保存——默认Quill会将图片转为Base64嵌入HTML,若要将图片存储到服务器文件夹或SQL数据库,需要拦截Quill的图片插入事件,替换为后端上传逻辑,再将返回的图片URL插入编辑器内容。
解决方案步骤
1. 配置Quill编辑器的图片上传拦截
在Blazor项目的wwwroot目录下创建quill-config.js文件,拦截图片插入操作并调用Blazor后端方法完成上传:
window.quillImageHandler = { register: function (dotNetRef) { const quill = new Quill('#editor-container', { theme: 'snow', modules: { toolbar: [ ['image'] // 保留其他工具栏配置 ] } }); // 拦截工具栏的图片点击事件 quill.getModule('toolbar').addHandler('image', function () { const input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('accept', 'image/*'); input.setAttribute('multiple', true); // 支持多图选择 input.click(); input.onchange = async function () { const files = Array.from(input.files); for (const file of files) { // 调用Blazor后端上传方法 const imageUrl = await dotNetRef.invokeMethodAsync('UploadImage', file); // 将图片URL插入编辑器 const range = quill.getSelection(); quill.insertEmbed(range.index, 'image', imageUrl); quill.setSelection(range.index + 1); } }; }); } };
2. Blazor后端实现图片上传与整合逻辑
在页面组件中添加JS交互引用,实现图片上传方法,并整合到原有保存流程:
@inject IWebHostEnvironment WebHostEnv @inject MonthlySharingService monthlySharingService @implements IDisposable @code { private MarkupString preview; private MonthlySharing monthlySharing = new(); private string message = string.Empty; private DotNetObjectReference<YourComponentName>? _dotNetRef; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { _dotNetRef = DotNetObjectReference.Create(this); // 注册Quill图片处理逻辑 await JS.InvokeVoidAsync("quillImageHandler.register", _dotNetRef); // 原有HTML内容加载逻辑 bool loading = true; while (loading) { try { if (!string.IsNullOrEmpty(monthlySharing.Content)) { await QuillHtml.LoadHTMLContent(monthlySharing.Content); } loading = false; } catch { await Task.Delay(10); loading = true; } } } await base.OnAfterRenderAsync(firstRender); } // 供JS调用的图片上传方法 [JSInvokable] public async Task<string> UploadImage(IFormFile file) { if (file == null || file.Length == 0) return string.Empty; // 方案1:保存到服务器文件夹 var uploadPath = Path.Combine(WebHostEnv.WebRootPath, "uploads", "images"); if (!Directory.Exists(uploadPath)) Directory.CreateDirectory(uploadPath); var fileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}"; var filePath = Path.Combine(uploadPath, fileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } // 返回可访问的图片URL return $"/uploads/images/{fileName}"; // 方案2:保存到SQL数据库(替换上方代码) // using var memoryStream = new MemoryStream(); // await file.CopyToAsync(memoryStream); // var imageData = memoryStream.ToArray(); // // 调用服务层保存图片数据,返回关联标识 // var imageId = await imageService.SaveImage(imageData, file.ContentType, monthlySharing.Id); // return $"/api/images/{imageId}"; // 需对应图片读取接口 } private async Task Save() { message = "wait..."; // 获取已替换为图片URL的编辑器HTML内容 monthlySharing.Content = await QuillHtml.GetText(); if (monthlySharingService.AddUpdate(monthlySharing)) { message = "Your post is successfully created! "; monthlySharing = new(); } else { message = "Could not saved"; } } public void Dispose() { _dotNetRef?.Dispose(); } }
3. 关键配置与注意事项
- 若选择服务器文件夹存储,需在
Program.cs中配置静态文件访问:app.UseStaticFiles(); // 若uploads目录不在wwwroot,需额外配置: // app.UseStaticFiles(new StaticFileOptions // { // FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "uploads")), // RequestPath = "/uploads" // }); - 若选择SQL数据库存储,需创建图片关联表(如
ArticleImages),存储字节数组、ContentType、文章ID等字段,并实现接口返回图片流。 - 确保Quill编辑器容器ID(
#editor-container)与JS配置一致。
内容的提问来源于stack exchange,提问作者user21185171
相关产品推荐
相关产品推荐

