MVC EF如何同时添加图像和其他数据库的值

12 浏览
0 Comments

MVC EF如何同时添加图像和其他数据库的值

我正在寻求在将图像(作为字节!)上传到数据库时的支持,同时还要上传其他属性。我必须承认,作为一个编程新手,我在完成这个任务时遇到了一些困难,但是我基本上搞定了。现在我的问题是,每当我尝试利用这个模型时,它就会停止工作,并弹出以下错误消息:

输入不是有效的Base-64字符串,因为它包含一个非Base-64字符,超过两个填充字符,或在填充字符中包含非法字符。

ViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.ComponentModel.DataAnnotations;
namespace errandomWeb.Models
{
    public class PhotoCompetition
    {
        public int ID { get; set; }
        public string UserID { get; set; }
        public string FirstName { get; set; }
        public string Email { get; set; }
        public byte[] CompetitionPicture { get; set; }
        //[Required]
        [Display(Name = "通过勾选此框,我接受条款和条件")]
        //[CheckBoxRequired(ErrorMessage = "请接受我们的条款和条件参与活动。")]
        public bool TermsAndConditionsAccepted { get; set; }
        public DateTime TimeStamp { get; set; }
    }
}

View:

@model errandomWeb.Models.PhotoCompetition

@{

ViewBag.Title = "成为我们的模特";

}

@ViewBag.Title

你好

@Html.TextBoxFor(m => m.FirstName, new { @id = "photoCompetitionHeaderUserName", @class = "manageHeaderUserName", @placeholder = "陌生人", @disabled = true })

@Html.Partial("_ProfileLogout")

想成为我们的模特吗?

@Html.ValidationSummary("", new { @id = "photoCompetitionValidation", @class = "manageValidation" })

@using (Html.BeginForm("UploadCompetitionPicture", "errandom", FormMethod.Post, new { @id = "photoCompetitionForm", @class = "form-horizontal", @role = "form", @enctype = "multipart/form-data" }))

{

@Html.AntiForgeryToken()

上传您的照片并成为我们的模特!

@Html.HiddenFor(m => m.UserID)

@Html.HiddenFor(m => m.Email)

@Html.HiddenFor(m => m.FirstName)

@Html.HiddenFor(m => m.TimeStamp)

@Html.LabelFor(m => m.CompetitionPicture, new { @id = "photoCompetitionProfilePictureLabel", @class = "manageLabel col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-1 col-md-3 col-lg-offset-1 col-lg-4" })

选择文件...

@Html.TextBoxFor(m => m.CompetitionPicture, new { @id = "photoCompetitionProfilePictureField", @class = "manageField col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-0 col-md-7 col-lg-offset-0 col-lg-6", @type = "file", @style = "display: none" })

@Html.CheckBoxFor(m => m.TermsAndConditionsAccepted, new { @id = "photoCompetitionTermsAndConditionsField", @class = "photoCompetitionTermsAndConditionsField" })

@Html.LabelFor(m => m.TermsAndConditionsAccepted, new { @id = "photoCompetitionTermsAndConditionsLabel", @class = "photoCompetitionTermsAndConditionsLabel" })

@Html.ValidationMessageFor(m => m.TermsAndConditionsAccepted, "", new { @id = "photoCompetitionTermsAndConditionsValidation", @class = "manageValidation col-xs-offset-1 col-xs-10 col-sm-offset-1 col-sm-10 col-md-offset-4 col-md-7 col-lg-offset-5 col-lg-6" })

}

@Html.ActionLink("返回菜单", "Index", "", htmlAttributes: new { @id = "photoCompetitionReturnToMenuButton", @class = "manageReturnToMenuButton" })

@section Scripts {

@Scripts.Render("~/bundles/jqueryval")

}

Controller:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using errandomWeb.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
namespace errandomWeb.Controllers
{
    [Authorize]
    public class errandomController : Controller
    {
        private ApplicationDbContext DB = new ApplicationDbContext();
        // GET: /errandom/PhotoCompetition
        public ActionResult PhotoCompetition()
        {
            var model = new PhotoCompetition
            {
                UserID = User.Identity.GetUserId(),
                Email = User.Identity.GetUserName(),
                FirstName = User.Identity.Name,
                TimeStamp = DateTime.UtcNow.ToUniversalTime()
            };
            return View(model);
        }
        // POST: /errandom/PhotoCompetition
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult UploadCompetitionPicture()
        {
            string croppedImage = Request.Form["photoCompetitionCroppedPicture"];
            byte[] imageBytes = Convert.FromBase64String(croppedImage.Split(',')[1]);
            var userId = User.Identity.GetUserId();
            var participation = new PhotoCompetition
            {
                CompetitionPicture = imageBytes,
                UserID = User.Identity.GetUserId(),
                FirstName = "testcase",
                Email = User.Identity.GetUserName(),
                TermsAndConditionsAccepted = false,
                TimeStamp = DateTime.UtcNow.ToUniversalTime(),
            };
            DB.PhotoCompetition.Add(participation);
            DB.SaveChanges();
            return View("Edit");
        }
    }
}

我想包含

TermsAndConditionsAccepted = model.TermsAndConditionsAccepted

所以该值实际上是从用户填写的表单中获取的,但由于上述原因,我遇到了问题。

非常感谢在这里得到的任何帮助,谢谢!

0
0 Comments

问题的原因是在上传图片和其他数据库值时遇到了困难。问题最终通过在控制器代码中对图片进行排除,然后分别添加其他字段和图片来解决。

解决方法是使用不同的类来作为视图模型和实体框架数据模型,并使用数据传输对象(DTO)。在DTO中,将CompetitionPicture属性定义为字符串而不是字节数组,并在设置模型的CompetitionPicture值时进行转换。这种设计更好,因为不需要将内部模型细节暴露给视图。

使用DTO的一些好处可以参考:[learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5](https://learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5)

0
0 Comments

问题出现的原因是在使用模型时,尝试将图像保存到数据库时发生了错误。在使用模型时,控制器中的Convert方法调用的Split方法返回了错误的结果,导致无法解码base64字符串。问题可能出在客户端javascript代码中生成base64字符串的函数toDataURL(),该函数返回的值包含了一个前缀,取决于图像的格式。默认情况下,toDataURL()函数使用png格式,返回的值的前缀类似于data:image/png;base64,...。实际的值位于前缀之后,通过逗号分隔,因此需要使用split方法将其读取到控制器中。可能是由于接收到的格式前缀不同,导致split方法无法正确获取值。可以通过在客户端使用console.log(canvas.toDataURL())来调试并查看实际的值。可能会发现服务器接收到的值与客户端生成的值不同(可能被截断)。可以比较客户端中值的控制台输出和服务器中变量croppedImage的内容或Split后的值。建议使用正则表达式来移除base64值中不需要的前缀,这样更安全。在链接中可以找到一些示例正则表达式的用法。如果使用模型时出现问题,而不使用模型时可以正常工作,建议检查一下在控制器中变量croppedImage的值,在更改模型时是否有任何不同。可以将croppedImage的值(或至少字符串的开头部分)粘贴在这里,以便查看发生了什么。目前没有想到与EF相关的原因会导致这个异常,因为异常是由Convert.FromBase64String引起的。

0