使用Razor、JavaScript/C#实现页面文件上传:点击创建按钮文件未保存且报错
Razor页面文件上传问题排查与解决
针对你遇到的文件未保存且弹出“无法访问此站点”的问题,结合你提供的代码,从后端、前端两方面梳理问题和修复方案:
一、后端代码问题修复
你提供的代码不完整,且存在几个关键问题:
1. 补充完整请求逻辑
当前代码仅处理了文件保存,缺少将Contratos实体保存到数据库的逻辑,也没有请求响应返回。如果没有正确的返回结果,前端会因请求超时或无响应报错。补充完整代码:
private readonly YourDbContext _context; private readonly IWebHostEnvironment _webHostEnv; // 构造函数注入DbContext和IWebHostEnvironment public ContratosController(YourDbContext context, IWebHostEnvironment webHostEnv) { _context = context; _webHostEnv = webHostEnv; } [HttpPost] public async Task<IActionResult> Create([Bind("ID,Inicio,Vencimento,ImovelId,LocatarioId,Ativo,ContratoPdf")] Contratos contratos, IFormFile arquivo) { if (ModelState.IsValid) { try { if (arquivo != null && arquivo.Length > 0) { // 替换硬编码路径,使用IWebHostEnvironment获取安全目录(推荐存到wwwroot下的子目录) string diretorioDestino = Path.Combine(_webHostEnv.WebRootPath, "Arquivos", "Contratos"); if (!Directory.Exists(diretorioDestino)) { Directory.CreateDirectory(diretorioDestino); } // 生成唯一文件名,避免重名覆盖 string nomeArquivo = $"{Guid.NewGuid()}_{Path.GetFileName(arquivo.FileName)}"; string caminhoCompleto = Path.Combine(diretorioDestino, nomeArquivo); using (var stream = new FileStream(caminhoCompleto, FileMode.Create)) { await arquivo.CopyToAsync(stream); } contratos.ContratoPdf = nomeArquivo; } // 将实体保存到数据库 _context.Add(contratos); await _context.SaveChangesAsync(); // 重定向到列表页,返回正确响应 return RedirectToAction(nameof(Index)); } catch (Exception ex) { // 捕获异常,添加到ModelState,返回页面显示错误 ModelState.AddModelError(string.Empty, $"文件保存失败:{ex.Message}"); } } // 模型验证失败或出错时,返回创建页面 return View(contratos); }
2. 关键优化点
- 避免硬编码路径:用
IWebHostEnvironment获取WebRootPath(wwwroot目录),避免部署时权限或路径不存在问题,同时保证跨平台兼容性。 - 生成唯一文件名:用
Guid拼接原文件名,防止同名文件覆盖。 - 添加异常捕获:捕获文件保存或数据库操作的异常,将错误信息返回前端,避免请求直接崩溃导致“无法访问站点”。
- 完善请求响应:无论成功失败都返回明确的ActionResult,确保前端能正确接收响应。
二、前端Razor页面配置
前端表单必须满足以下要求,否则文件无法正确提交:
1. 表单设置enctype属性
表单必须添加enctype="multipart/form-data",否则文件不会被包含在请求中:
<form asp-action="Create" enctype="multipart/form-data"> <!-- 其他表单字段 --> <div class="form-group"> <label asp-for="ContratoPdf" class="control-label"></label> <input type="file" name="arquivo" class="form-control" /> <span asp-validation-for="ContratoPdf" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="创建" class="btn btn-primary" /> </div> </form>
2. 文件输入名称匹配
文件输入的name属性必须和后端方法的IFormFile参数名一致(这里是arquivo),否则模型绑定失败,arquivo会为null。
三、常见额外问题排查
如果以上修复后仍报错,检查以下点:
- 目录权限:确保应用程序对目标目录有读写权限(比如IIS应用池身份、开发时的当前用户)。
- 文件大小限制:ASP.NET Core默认限制上传文件大小为30MB,若上传大文件,需在
Program.cs中配置:
builder.Services.Configure<FormOptions>(options => { options.MultipartBodyLengthLimit = 104857600; // 100MB });
- AJAX上传的特殊处理:如果用JavaScript AJAX提交,必须用
FormData对象,且不能设置contentType为application/json:
document.querySelector('form').addEventListener('submit', async function(e) { e.preventDefault(); const formData = new FormData(this); const response = await fetch(this.action, { method: 'POST', body: formData }); if (response.ok) { window.location.href = '/Contratos/Index'; } else { // 处理错误 const errorText = await response.text(); alert(errorText); } });
内容的提问来源于stack exchange,提问作者Lucas Barbosa
相关产品推荐
相关产品推荐

