Blazor开发MCQ页面时不同题目上传图片均保存为同一张问题求解
问题根因
- SfUploader ID冲突:所有动态生成的上传组件使用固定ID
UploadFilesMCQ,同页面重复ID的Syncfusion组件会出现绑定错乱,所有上传操作最终都会关联到最后渲染的上传实例,导致所有行读取同一份文件数据。 - 全局变量覆盖:你当前使用的
filesMCQ、contentMCQ、mCQ都是页面级全局变量,每次新增行、上传新文件时,新数据会直接覆盖旧值,之前行对应的文件数据没有被独立存储,最终保存时所有行都读取最后一次上传的内容。 - 实体与文件未绑定:
tMCQ实体没有单独存储对应行的上传文件信息,仅赋值了路径属性,保存时无法匹配到对应行的专属文件流。
修复步骤
1. 给上传组件配置唯一动态ID
在循环渲染MCQ行的代码中,用当前行的唯一标识拼接上传组件ID,避免重复:
@foreach(var item in tblMCQ) { <SfUploader ID="@($"UploadFilesMCQ_{item.MCQ_Id}")" AllowedExtensions=".png,.jpeg,.jpg" > <UploaderEvents ValueChange="@(args => onChangeMCQ(args, item))" OnRemove="@(args => onRemoveMCQ(args, item))"></UploaderEvents> <UploaderTemplates> <Template Context="HttpContext"> <td> <img class="upload-image" alt="Preview Image @(HttpContext.Name)" width="100" height="100" src="@(item.FilesMCQ.Count > 0 ? item.FilesMCQ.Where(f => f.Name == HttpContext.Name)?.FirstOrDefault()?.Path : string.Empty)" /> </td> <td> <div style="padding: 7px; width: 50px;"> <h5 title="@(HttpContext.Name)">@(HttpContext.Name)</h5> <i>@(HttpContext.Size) Bytes</i> </div> </td> </Template> </UploaderTemplates> </SfUploader> }
2. 改造tMCQ实体,新增专属文件存储字段
将原来的全局文件存储字段移动到tMCQ类内部,保证每行数据独立存储自己的上传文件:
public class tMCQ { // 原有字段保留 public int MCQ_Id { get; set; } public string MCQDescription { get; set; } public string Code { get; set; } public string ImagePath { get; set; } // 新增每行专属文件存储字段 public List<fileInfos> FilesMCQ { get; set; } = new List<fileInfos>(); public MultipartFormDataContent ContentMCQ { get; set; } }
3. 修改上传事件逻辑,绑定到当前行实例
修改onChangeMCQ方法,接收当前行的tMCQ实例,将上传的文件数据存入当前行的专属字段,不再操作全局变量:
private void onChangeMCQ(UploadChangeEventArgs args, tMCQ currentRow) { currentRow.FilesMCQ.Clear(); currentRow.ContentMCQ?.Dispose(); currentRow.ContentMCQ = new MultipartFormDataContent(); foreach (var file in args.Files) { currentRow.FilesMCQ.Add(new fileInfos { Name = file.FileInfo.Name, Size = file.FileInfo.Size, Path = file.Url }); currentRow.ContentMCQ.Add(new StreamContent(file.OpenReadStream()), file.FileInfo.Name, file.FileInfo.Name); } }
4. 简化AddLine方法,移除全局变量操作
删除页面级的全局filesMCQ、contentMCQ变量,调整AddLine逻辑:
private async void AddLine() { cursor(true); tMCQ item = new tMCQ(); MCQNumber++; item.MCQDescription = mCQ.MCQDescription; item.MCQ_Id = MCQNumber; item.Code = char.ConvertFromUtf32(64 + MCQNumber); tblMCQ.Add(item); CodeNumber++; // 仅清空临时输入变量 mCQ.MCQDescription = ""; }
5. 调整保存逻辑,逐行处理专属文件
保存时循环遍历每行tMCQ,单独处理对应行的上传文件:
foreach (var item in tblMCQ) { if (item.ContentMCQ != null && item.FilesMCQ.Any()) { string ext = item.FilesMCQ.First().Name.Split('.').Last(); string FileName = $"{Guid.NewGuid()}.{ext}"; string savePath = new ExtensionMethods().SaveTo(FileName); item.ImagePath = savePath; using (var ms = new FileStream(savePath, FileMode.Create)) { await item.ContentMCQ.First().CopyToAsync(ms); } // 处理完释放资源 item.ContentMCQ.Dispose(); } }
内容的提问来源于stack exchange,提问作者Ahtasham ul haq
相关产品推荐
相关产品推荐

