You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET中JS传附件至C#方法报错及接收为空问题求助

问题分析与解决方案

问题根源

  1. Illegal Invocation错误:jQuery默认会自动处理AJAX请求的数据格式,当传递FormData对象时,必须禁用自动处理逻辑,否则会触发该错误;同时原URL末尾多了一个多余的=符号,导致请求路径无效。
  2. 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接收:

  1. JS中修改selectedAttachments存储原始File对象:
    const attachment = {
        file: file,
        name: fileName,
        type: fileType
    };
    
  2. 上传时直接将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配置同上
    }
    
  3. C#方法参数改为:
    public async Task<IActionResult> OnPostSaveAttachments(List<IFormFile> files, List<string> names)
    

内容的提问来源于stack exchange,提问作者Maksio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:01:59