前后端分离Web API项目AJAX上传图片并存库及存前端目录咨询
解决方案
一、前端代码修改
你当前使用JSON格式提交数据,无法传输二进制文件,需要改用FormData格式提交,同时调整AJAX配置。
首先确保图片选择框为文件类型:
<input type="file" class="picture" accept="image/*">
修改后的AJAX代码如下:
$('.empOfficialDetails').click(function (ev) { ev.preventDefault(); // 改用FormData承载数据 var formData = new FormData(); formData.append("UserName", $('#username').val()); formData.append("UPassword", $('#userpass').val()); formData.append("OfficialEmailAddress", $('#officialemail').val()); formData.append("Departments", $('#departments :selected').text()); formData.append("Designation", $('#designation :selected').text()); formData.append("RoleID", $('#role').val()); formData.append("Role", $('#role :selected').text()); formData.append("ReportToID", $('#reportToID').val()); formData.append("ReportTo", $('#reportTo :selected').text()); formData.append("JoiningDate", $('#joindate').val()); formData.append("IsAdmin", $('#isAdmin :selected').val() ? 1 : 0); formData.append("IsActive", $('#isActive :selected').val() ? 1 : 0); formData.append("IsPermanent", $('#isPermanent :selected').val() ? 1 : 0); formData.append("DateofPermanancy", $('#permanantdate').val()); formData.append("HiredbyReference", $('#hiredbyRef :selected').val() ? 1 : 0); formData.append("HiredbyReferenceName", $('#refePersonName').val()); formData.append("BasicSalary", $('#basicSalary').val()); // 追加图片文件 if($('.picture')[0].files.length > 0){ formData.append("EmpPic", $('.picture')[0].files[0]); } if ($('#username').val() && $('#userpass').val() && $('#officialemail').val() && $('#departments :selected').text() && $('#designation :selected').text() && $('#role :selected').text() && $('#isAdmin :selected').val() && $('#isPermanent :selected').val()) { $.ajax({ url: 'http://localhost:1089/api/Employee/EmpOfficialDetails', type: "POST", dataType: 'json', contentType: false, // 让浏览器自动生成带分隔符的请求头 processData: false, // 禁止jQuery处理FormData data: formData, beforeSend: function () { $("#dvRoomsLoader").show(); }, complete: function () { $("#dvRoomsLoader").hide(); }, success: function (data) { var ID = parseInt(data); if (ID > 0) { $(".HiddenID").val(data); $('#official').css('display', 'block'); $('#official').html("Employees Official details added successfully...!"); $('#official').fadeOut(25000); $("#dvRoomsLoader").show(); $('.empOfficialDetails').html("Update <i class='fa fa-angle-right rotate-icon'></i>"); } else { $('#official').find("alert alert-success").addClass("alert alert-danger").remove("alert alert-success"); } }, error: function (ex) { alert("There was an error while submitting employee data"); console.log(ex); } }); } return false; });
二、后端代码修改
2.1 接口调整
原接口接收JSON序列化的Employee实体,现在需要兼容FormData格式,同时获取上传的文件流,修改后代码如下:
[Route("api/Employee/EmpOfficialDetails")] [HttpPost] public int? EmpOfficialDetails() { try { // 从FormData解析字段构造Employee对象 Employee emp = new Employee(); emp.UserName = HttpContext.Current.Request.Form["UserName"]; emp.UPassword = HttpContext.Current.Request.Form["UPassword"]; emp.OfficialEmailAddress = HttpContext.Current.Request.Form["OfficialEmailAddress"]; emp.Departments = HttpContext.Current.Request.Form["Departments"]; emp.Designation = HttpContext.Current.Request.Form["Designation"]; emp.RoleID = Convert.ToInt32(HttpContext.Current.Request.Form["RoleID"]); emp.Role = HttpContext.Current.Request.Form["Role"]; emp.ReportToID = Convert.ToInt32(HttpContext.Current.Request.Form["ReportToID"]); emp.ReportTo = HttpContext.Current.Request.Form["ReportTo"]; emp.JoiningDate = Convert.ToDateTime(HttpContext.Current.Request.Form["JoiningDate"]); emp.IsAdmin = Convert.ToInt32(HttpContext.Current.Request.Form["IsAdmin"]); emp.IsActive = Convert.ToInt32(HttpContext.Current.Request.Form["IsActive"]); emp.IsPermanent = Convert.ToInt32(HttpContext.Current.Request.Form["IsPermanent"]); emp.DateofPermanancy = Convert.ToDateTime(HttpContext.Current.Request.Form["DateofPermanancy"]); emp.HiredbyReference = Convert.ToInt32(HttpContext.Current.Request.Form["HiredbyReference"]); emp.HiredbyReferenceName = HttpContext.Current.Request.Form["HiredbyReferenceName"]; emp.BasicSalary = Convert.ToDecimal(HttpContext.Current.Request.Form["BasicSalary"]); // 获取上传的图片文件 HttpPostedFileBase picFile = HttpContext.Current.Request.Files["EmpPic"]; string picRelativePath = ""; if(picFile != null && picFile.ContentLength > 0) { // 生成唯一文件名避免重名 string fileExt = Path.GetExtension(picFile.FileName); string fileName = Guid.NewGuid().ToString("N") + fileExt; // 读取配置的存储路径 string saveRootPath = ConfigurationManager.AppSettings["EmployeeImageSavePath"]; if(!Directory.Exists(saveRootPath)) Directory.CreateDirectory(saveRootPath); string fullSavePath = Path.Combine(saveRootPath, fileName); // 保存文件到指定目录 picFile.SaveAs(fullSavePath); // 生成前端可直接访问的相对路径 picRelativePath = $"/assets/img/profiles/employeeImages/{fileName}"; // 调用你的EmployeeImage方法,直接传入picFile参数即可 // EmployeeImage(emp, picFile); } emp.CurrentPicURL = picRelativePath; // 调用原有业务逻辑 var id = Emp_OfficialDetails(emp); return id; } catch (Exception ex) { InternalServerError(ex); } return null; }
2.2 跨项目存储图片适配
独立前后端工程默认无法跨工程写入文件,按场景选择适配方案:
- 开发环境:在后端Web.config的AppSettings节点配置前端图片目录的绝对路径,比如:
后端直接读取该路径写入文件即可。<add key="EmployeeImageSavePath" value="D:/你的前端项目根目录/assets/img/profiles/employeeImages"/> - 生产环境:建议将图片存储到后端静态资源服务、云OSS等公共存储位置,前端直接访问对应的资源URL即可,无需写入前端工程目录。
三、注意事项
- 后端需要配置CORS跨域规则,允许前端域名的POST请求
- 调整Web.config的文件上传大小限制,示例为允许最大10M上传:
<httpRuntime targetFramework="你的版本号" maxRequestLength="10240" />
内容的提问来源于stack exchange,提问作者Syed Muhammad Aousaja Ali
相关产品推荐
相关产品推荐

