ASP.NET中JS传附件至C#方法报错及接收为空问题求助
问题分析与解决方案
问题根源
- Illegal Invocation错误:jQuery默认会自动处理AJAX请求的数据格式,当传递
FormData对象时,必须禁用自动处理逻辑,否则会触发该错误;同时原URL末尾多了一个多余的=符号,导致请求路径无效。 - Attachments计数为0:原代码中用
Uint8Array存储文件内容,无法被JSON.stringify正确序列化,后端无法解析;且AttachmentData类的Content字段为Stream类型,无法直接从JSON数据绑定。
一、修正JavaScript代码
修复AJAX配置、调整文件内容序列化方式,并完善附件删除逻辑:
<div class="file-input-container"> <label for="fileInput" class="file-label">Wybierz załącznik</label> <br /> <input type="file" id="fileInput" class="file-input" name="file" /> </div> <ul id="attachment-list"></ul> <hr /> <script> const fileInput = document.getElementById('fileInput'); const attachmentList = document.getElementById('attachment-list'); let selectedAttachments = []; fileInput.addEventListener('change', handleFileUpload); function handleFileUpload(event) { const file = event.target.files[0]; const fileName = file.name; const fileType = file.type; const reader = new FileReader(); reader.onload = (e) => { // 将文件内容转为Base64字符串,确保可被JSON序列化 const fileContentBase64 = btoa(String.fromCharCode(...new Uint8Array(e.target.result))); const attachment = { name: fileName, content: fileContentBase64, type: fileType }; selectedAttachments.push(attachment); saveAttachmentsToServer(selectedAttachments); }; reader.readAsArrayBuffer(file); const listItem = document.createElement('li'); listItem.classList.add('attachment-item'); const attachmentName = document.createElement('span'); attachmentName.classList.add('attachment-name'); attachmentName.textContent = fileName; const attachmentDelete = document.createElement('span'); attachmentDelete.classList.add('attachment-delete'); attachmentDelete.textContent = '×'; attachmentDelete.addEventListener('click', () => { listItem.remove(); // 同步删除数组中对应的附件 selectedAttachments = selectedAttachments.filter(att => att.name !== fileName); saveAttachmentsToServer(selectedAttachments); }); listItem.setAttribute('data-name', fileName); listItem.setAttribute('data-type', file.type); listItem.appendChild(attachmentName); listItem.appendChild(attachmentDelete); attachmentList.appendChild(listItem); event.target.value = ''; } function saveAttachmentsToServer(attachments) { const formData = new FormData(); formData.append('attachments', JSON.stringify(attachments)); $.ajax({ url: "?handler=SaveAttachments", // 移除多余的=符号 method: "POST", // 明确指定POST方法,对应后端OnPost前缀的方法 data: formData, processData: false, // 禁用jQuery对FormData的自动处理 contentType: false, // 让浏览器自动设置正确的Content-Type success: function () { console.log('Załączniki zapisane'); }, error: function (error) { console.error('Wystąpił błąd podczas zapisu załączników', error); } }); } </script>
二、调整C#代码
修改模型字段类型,适配Base64字符串的解析与转换:
public async Task<IActionResult> OnPostSaveAttachments(List<AttachmentData> attachments) { try { foreach (var attachmentData in attachments) { if (!string.IsNullOrEmpty(attachmentData.Content)) { // 将Base64字符串转为字节数组 var attachmentContent = Convert.FromBase64String(attachmentData.Content); if (attachmentContent != null && attachmentContent.Length > 0) { string attachmentName = attachmentData.Name; string attachmentType = attachmentData.Type; string blobName = Guid.NewGuid().ToString(); BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString); BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName); BlobClient blobClient = containerClient.GetBlobClient(blobName); // 将字节数组转为MemoryStream用于Blob上传 using var stream = new MemoryStream(attachmentContent); await blobClient.UploadAsync(stream, new BlobUploadOptions { HttpHeaders = new BlobHttpHeaders { ContentType = attachmentType // 设置文件MIME类型 } }, overwrite: true); Console.WriteLine("Załącznik zapisany: " + attachmentName); } else { Console.WriteLine("Błąd: Brak zawartości załącznika."); } } else { Console.WriteLine("Błąd: Zawartość załącznika jest pusta."); } } return Page(); } catch (Exception ex) { Console.WriteLine("Błąd: " + ex.Message); return BadRequest("Wystąpił błąd podczas zapisywania załączników."); } } public class AttachmentData { public string Name { get; set; } public string Content { get; set; } // 改为string存储Base64格式内容 public string Type { get; set; } }
可选优化方案(直接传递文件对象)
如果不想用Base64,可直接传递原始File对象,C#用IFormFile接收:
- JS中修改
selectedAttachments存储原始File对象:const attachment = { file: file, name: fileName, type: fileType }; - 上传时直接将File对象加入FormData:
function saveAttachmentsToServer(attachments) { const formData = new FormData(); attachments.forEach((att, index) => { formData.append(`files[${index}]`, att.file); formData.append(`names[${index}]`, att.name); }); // AJAX配置同上 } - C#方法参数改为:
public async Task<IActionResult> OnPostSaveAttachments(List<IFormFile> files, List<string> names)
内容的提问来源于stack exchange,提问作者Maksio
相关产品推荐
相关产品推荐

