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

.NET Core 6 Razor非MVC环境AJAX带进度条文件上传接收问题

.NET Core 6非MVC模式(Razor Pages)AJAX带进度条文件上传后端接收方案

问题背景

使用.NET Core 6非MVC模式(Razor Pages)实现AJAX带进度条文件上传,前端请求已发送文件数据,但后端C#始终接收为null,需将文件转为字节存入数据库,同时保留上传进度显示功能。

前端代码修正

原JavaScript使用FileReader.readAsDataURL将文件转为Base64字符串传递,导致后端无法直接用标准文件接收方式处理。改为使用FormData直接传递文件对象,既符合HTTP文件上传规范,又能保留进度条功能:

HTML代码(无需修改)

<input type="file" id="uploaddoc" style="display: none;" accept=".doc, .docx, .pdf, .png, .jpg, .jpeg" />
<input type="button" value="Browse..." class="btn btn-primary" style="max-width: 150px;"
     onclick="document.getElementById('uploaddoc').click();" />
<div class="progress" id="progCollapse" style="position: absolute; height: 10px; 
     width: 425px; margin-left: -15px; margin-top: 5px; display: none">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar"
     id="progress" style="width: 0" aria-valuenow="0" aria-valuemin="0"
     aria-valuemax="100"></div></div>

修改后的JavaScript代码

function uploadDoc() {
  const fileInput = document.getElementById("uploaddoc");
  const file = fileInput.files[0];

  if (!file) return;

  // 初始化进度条
  $("#progCollapse").show();
  document.getElementById("progress").style.width = "0%";

  // 创建FormData对象,用于传递文件
  const formData = new FormData();
  formData.append("doc", file); // "doc"对应后端参数名
  formData.append("filename", file.name); // 可选:传递文件名

  $.ajax({
    xhr: function () {
      const xhr = new window.XMLHttpRequest();
      // 监听上传进度
      xhr.upload.addEventListener("progress", function (evt) {
        if (evt.lengthComputable) {
          const percentComplete = (evt.loaded / evt.total) * 100;
          document.getElementById("progress").style.width = percentComplete + "%";
          if (percentComplete === 100) {
            $("#progCollapse").hide();
            document.getElementById("progress").style.width = "0%";
          }
        }
      }, false);
      return xhr;
    },
    beforeSend: function (xhr) {
      // 传递防跨站请求伪造令牌
      xhr.setRequestHeader("RequestVerificationToken",
        $('input:hidden[name="__RequestVerificationToken"]').val());
    },
    type: 'POST',
    url: "/PageName?handler=SaveFile",
    contentType: false, // 让浏览器自动设置正确的Content-Type(包含boundary)
    processData: false, // 禁止jQuery处理FormData
    data: formData,
    success: function (response) {
      // 处理上传成功后的逻辑
      console.log("上传成功", response);
    },
    error: function (xhr, status, error) {
      // 处理错误
      console.error("上传失败", error);
      $("#progCollapse").hide();
      document.getElementById("progress").style.width = "0%";
    }
  });
}

后端C#实现(Razor Pages)

在对应的PageModel类中,实现OnPostSaveFile方法,通过IFormFile接收文件,读取为字节数组后存入数据库:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.IO;

public class PageNameModel : PageModel
{
    // 假设你有数据库上下文依赖注入
    // private readonly YourDbContext _dbContext;

    // public PageNameModel(YourDbContext dbContext)
    // {
    //     _dbContext = dbContext;
    // }

    public async Task<IActionResult> OnPostSaveFile(IFormFile doc, string filename)
    {
        if (doc == null || doc.Length == 0)
        {
            return BadRequest("未接收到有效文件");
        }

        // 将文件转为字节数组
        byte[] fileBytes;
        using (var memoryStream = new MemoryStream())
        {
            await doc.CopyToAsync(memoryStream);
            fileBytes = memoryStream.ToArray();
        }

        // 这里执行存入数据库的逻辑
        // 示例:_dbContext.FileRecords.Add(new FileRecord { Filename = filename, FileData = fileBytes });
        // await _dbContext.SaveChangesAsync();

        return new JsonResult(new { success = true, message = "文件上传成功" });
    }
}

关键说明

  1. 原方案失败原因:原代码将文件转为Base64字符串传递,不符合HTTP标准文件上传格式,导致IFormFile无法识别。使用FormData直接传递文件对象是标准方式,后端可直接用IFormFile接收。
  2. 进度条逻辑:xhr.upload.addEventListener("progress")监听的是文件上传到服务器的进度,这是进度条的正确触发点,无需额外监听xhr本身的progress事件。
  3. CSRF令牌:Razor Pages默认启用防跨站请求伪造保护,需在AJAX请求头中传递RequestVerificationToken(对应页面中隐藏的__RequestVerificationToken输入框的值),否则请求会被拒绝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:36:31