【问题标题】:asp.net mvc: save base64 image data to tableasp.net mvc:将base64图像数据保存到表中
【发布时间】:2013-12-07 13:04:02
【问题描述】:

我想从画布中捕获图片,将其设为 base64 并将其保存到数据库中。是否可以将base64直接保存到表中? 这是我已经来的地方:

查看:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var img = document.getElementById("image0");
ctx.drawImage(img, 0, 0);
//drawing image into myCanvas

var imag = canvas.toDataURL("image/png");
//making base64 from that image

document.getElementById('imag').value = imag;
//passing base64 to @Html.TextAreaFor(model => model.IMG, new {id = "imag"}) prior to submitting

型号:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;

namespace myApp.Models
{ 
public class MYCLASS
    {
     public int ...
     public string ...
     public string IMG { get; set; }
    }
}

控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult myImageToDB(MYCLASS myclass)
{

   if (ModelState.IsValid)
   {
      db.MYCLASSs.Add(myclass);
      db.SaveChanges();
      //here it fails on db.SaveChanges()
      return RedirectToAction("Detail", "M35");
   }
   return View(myclass);
}

提交后,我只从 MS VS 得到这个答案:

System.Data.Entity.Validation.DbEntityValidationException:验证 一个或多个实体失败。

我添加的时候出现的问题

public string IMG { get; set; }

进入模型。当我现在禁用时

document.getElementById('imag').value = imag;

一切正常。

谢谢

【问题讨论】:

  • 服务器上的模型是什么样的?看来您已经指定了验证规则。
  • 您的错误是EF错误,请提供更多细节
  • 我添加了一些额外的细节。请让我知道是否需要更多内容。谢谢
  • 请查看此问题以了解您的验证错误实际上是什么 - stackoverflow.com/questions/5400530/…
  • Floradu88,Tommy,所以您会说代码本身没有问题,但 EF 有问题吗?汤米,您发布的链接我需要“翻译”,但还没有从那里的答案中得到它:)

标签: c# asp.net-mvc entity-framework html5-canvas base64


【解决方案1】:

您有需要 Base64 的理由吗?它增加了必须从数据库中编码和解码的开销。如果可以,最好将图像数据(未编码)简单地存储为数据库中的二进制 blob。也就是说,如果您的图片尺寸较小。

Microsoft 提供了一个很好的文档 (https://research.microsoft.com/pubs/64525/tr-2006-45.pdf),名为“To BLOB or not to BLOB”,关于您是否应该将图像存储在数据库中。基本规则是,如果您的图像小于或等于 256KB,则可以存储在 DB 中。如果大于 1MB,那么最好将图像存储在文件系统上并直接从服务器中提供它们。

MS SQL Server 2012 可以通过其新的 FILETABLE 功能为您自动管理二进制数据的文件系统存储:http://blogs.msdn.com/b/mvpawardprogram/archive/2012/07/23/sql-server-2012-migrating-blobs-to-filetables.aspx

【讨论】:

  • 如果它们大于 256KB 但小于 1MB 怎么办? :)
  • 我想将它直接存储到数据库的原因是,并非所有创建后的记录都会被“保存”以供以后使用。因此,如果我将图像存储在文件系统中,那么我需要删除 db 记录以及文件系统中的图像,而不是只删除 db 记录。是的,图片大小不超过 256KB。
  • nevo,我明白了。但是,如果您的图像大于 1MB,您的性能可能会受到影响。没关系,存储在数据库中就可以了。但为了获得更好的性能,请不要使用 base64,只需存储为 blob。在 2012 之前的 SQL Server 版本中,他们甚至提供了“IMAGE”类型:technet.microsoft.com/en-us/library/ms187993.aspx 如果您有幸使用 Server 2012,它的新 FILETABLE 可以为您提供两全其美的优势。它为您管理文件系统上的数据! blogs.msdn.com/b/mvpawardprogram/archive/2012/07/23/…
  • 我会说我只是好奇这种新方法是否会更容易编程。将图像存储到文件系统中我已经在我以前的应用程序中尝试过。
  • @nemik,也感谢您的回答。希望我有更大的声誉,所以我会将您的提示标记为有用。我将文件系统存储为备份。永远不知道:)
【解决方案2】:

根据您的错误消息,发生错误是因为您的模型不符合数据库规则。例如,您正在向不可为空的值发送空值,或者您试图在列中放入太多信息(128 字节列中有 255 个字节)。使用此链接中的信息可帮助您准确发现实体的哪些属性失败 - Validation failed for one or more entities while saving changes to SQL Server Database using Entity Framework

既然你已经这样做了,我看到你的实际实体错误是

IMG 错误:字段 IMG 必须是字符串或数组类型,最大 '4000' 的长度。

varchar(n|MAX) 的限制为 4000 如果您在声明它时指定一个整数 (varchar(4000))。但是,使用varchar(MAX) 可以在每条记录的一个字段中为您提供 2GB 的存储空间。有了这个,我们需要查看您在 EF 实现中是先使用代码还是先使用数据库。如果您首先使用代码,请使用varchar(MAX) 注释您的列,如下所示。

[Column(TypeName = "varchar(MAX)")]
public string Img {get;set;}

如果您首先使用数据库,然后转到您的数据库(Sql Management Studio),右键单击表并选择设计。将图像字段更新为varchar(MAX) 作为类型并保存。要更新 EF,请打开您的 EF 设计器,删除现有的图像表,然后右键单击表面并选择从数据库中更新模型,然后按照步骤重新添加您的表。

编辑

根据 OP 的回复,我们还应该介绍如何在 SQL CE 中制作大型 varchar 列。要先针对 SQL CE 编写代码,请使用以下代码 sn-p:

[Column(TypeName = "ntext")]
[MaxLength] 
public string Img {get;set;}

【讨论】:

  • 感谢您的详细解答。就是这样。对于我的应用程序开发,我使用 SQL CE(在我的 Q 中没有说明)所以最后我发现它是 SQL CE 的 ntext (varchar(MAX)然后用于 SQL Server)。但是工作得很好,我的 db 列中已经存储了 base64 数据:) SQL CE [Column(TypeName = "ntext")] public string Img {get;set;}的最终代码 sn-p >
  • @nevo - 太棒了,我更新了我的答案以涵盖 SQL CE!
  • 坏消息。不幸的是,我在保存之前确实以某种方式削弱(缩短)base64 字符串。这就是我能够将它保存到 "ntext" 字符串 的原因,如上所述。在我更正错误后,我再次收到 The field IMG must be a string or array type with the maximum length of '4000' 错误,无论 Img 字符串是 ntext。恐怕 SQL CE 不会像 base64 那样“吃掉”那个长字符串。还是有其他问题(需要解码/编码??)...
  • @nevo - 除了上面的评论,也看看这个 SO 问题 - stackoverflow.com/questions/15329877/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-18
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
  • 2022-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多