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

前后端分离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 &nbsp; <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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 23:09:03