首页 新闻 会员 周边 捐助

在控制器中上传图片的同时将图片以二进制的形式添加到oracle数据库

0
悬赏园豆:40 [已解决问题] 解决于 2016-11-07 14:43

下面我贴出方法以及截图说明,各位大神麻烦提点建议

这里是上传图片的代码

        /// <summary>
        /// 文件上传
        /// </summary>
        public void Uploadimage()
        {
            try
            {
                //获取当前Post过来的file集合对象,在这里我只获取了<input type='file' name='fileUp'/>的文件控件
                HttpPostedFileBase file = Request.Files["fileUp"];
                if (file != null)
                {
                    //当前文件上传的目录
                    string path = Server.MapPath("~/images/Insurancetype/");
                    string savepath = "../images/Insurancetype/" + System.IO.Path.GetFileName(file.FileName);
                    //当前待上传的服务端路径
                    string imageUrl = path + Path.GetFileName(file.FileName);
                    //当前文件后缀名
                    string ext = Path.GetExtension(file.FileName);
                    //验证文件类型是否正确
                    if (!ext.Equals(".gif") && !ext.Equals(".jpg") && !ext.Equals(".png") && !ext.Equals(".bmp"))
                    {
                        //这里window.parent.uploadSuccess()是我在前端页面中写好的javascript function,此方法主要用于输出异常和上传成功后的图片地址
                        Response.Write("<script>window.parent.uploadSuccess('你上传的文件格式不正确!上传格式有(.gif、.jpg、.png、.bmp)');</script>");
                        Response.End();
                    }
                    //验证文件的大小
                    else if (file.ContentLength > 1048576)
                    {
                        //这里window.parent.uploadSuccess()是我在前端页面中写好的javascript function,此方法主要用于输出异常和上传成功后的图片地址
                        Response.Write("<script>window.parent.uploadSuccess('你上传的文件不能大于1048576KB!请重新上传!');</script>");
                        Response.End();
                    }
                    else
                    {
                        
                        //Session["imageUrl"] = savepath;
                        //开始上传
                        file.SaveAs(imageUrl);
                        //这里window.parent.uploadSuccess()是我在前端页面中写好的javascript function,此方法主要用于输出异常和上传成功后的图片地址
                        //如果成功返回的数据是需要返回两个字符串,我在这里使用了|分隔  例: 成功信息|/Test/hello.jpg
                        Response.Write("<script>window.parent.uploadSuccess('Upload Success!|/Test/" + file.FileName + "');</script>");
                        Response.End();
                        //FileStream fs = new FileStream(file.FileName, FileMode.Open);
                        //byte[] er = new byte[file.ContentLength];
                        //fs.Read(er, 0, file.ContentLength);
                        //fs.Close();
                         
                        //FileStream fd = new FileStream(savepath, FileMode.Open);
                        //byte[] re = new byte[file.ContentLength];
                        //fd.Read(re, 0, file.ContentLength);
                        //fd.Close();

                        FileStream fr = new FileStream(imageUrl, FileMode.Open);
                        byte[] te = new byte[fr.Length];
                        fr.Read(te, 0, te.Length);
                        fr.Close();
                        Session["imageUrl"] = te;
                    }

                }
                else
                {
                    //上传失败
                    Response.Write("upload lose, no file!");
                    Response.End();
                }
            }
            catch
            {
                //上传失败
                Response.Write("upload lose!");
                Response.End();
            }
        }

这里是上传图片结束后,我写的转换二进制的代码,应该是有错误或者别的问题的,各位大神看一下

这里是添加的时候本来是接收图片的本地路径,但是效果不对,在上传图片完成后想转成二进制但没有成功,添加进数据库的是一个System.Io.FileStream这样的一个纯字符串

这是数据库的效果图:

我在网上搜了一下,说数据库想要这种效果,必须将图片转换成二进制,但我这里一直有误区,自己又不知道该改哪里,所以,各位大神们,给指点一二,或者能够给出例子

噜灬噜噜的主页 噜灬噜噜 | 初学一级 | 园豆:21
提问于:2016-11-04 09:46
< >
分享
最佳答案
0

误区很简单,你要保存到数据库的应该是二进制

但是你现在保存的是string

为啥呢?因为你把二进制给tostring了,看你的这句代码,就是你的红箭头的那句,你要写成=(byte[])Session["imageUrl"]

这样你可能会问你的那个是string类型,会报错,但是你必须这样添加,改一下F_FLOWSHEET的类型就可以了,然后在插入数据库的时候使用parameter的形式就实现插入数据库了

收获园豆:20
刘宏玺 | 专家六级 |园豆:14020 | 2016-11-04 10:26

您说的改一下F_FLOWSHEET的类型,数据库的类型已经是blob类型了,您看我可以在添加的时候,改动一下sql语句吗?像这种

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 10:34

哦,对了 ,您的意思是让我把在vs里model的F_FLOWSHEET的类型改了是吗?我在vs里model的类型是string类型。

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 10:39

@噜灬噜噜: 当然是这个意思了!

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 10:40

@刘宏玺: 了解了解,我去试试把vs里model里的F_FLOWSHEET类型换成byte,谢谢您了,可能一会还会再问您问题。。。。

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 10:42

@噜灬噜噜: insert到数据库的地方还要做parameter形式的改造,仔细看我第一次的回复,肯定能实现的!

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 10:44

@刘宏玺: 了解,但是现在在显示的时候就已经提示错误了,类型有问题,这样写难道不对吗?报了这个错误,提示model类型为System.IConvertible

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 10:55

@噜灬噜噜: 要写成byte[]类型啊老兄!

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 10:57

@刘宏玺: 大神  那我就不懂了,model里F_flowsheet的类型我已经换成byte[]  但这里的实体化 该怎么转呢?convert.tobyte(row["F_flowsheet"])已经不好使了,还有其他强转的方法吗?

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 11:10

@噜灬噜噜: 为啥要转呢?你说的是保存的时候吗?

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 11:11

@刘宏玺: 不是 这是在显示的时候  需要对数据实体化  实体化到F_flowsheet这里  类型不对 它就断了

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 11:12

 如果你说的是读取到页面的时候,那你直接输出就完事了,根本不用转换的!已经是流的形式了

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 11:13

@噜灬噜噜: 你多给我点代码,我看下你说要转的地方

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 11:14

@刘宏玺: 好  我把model层和dal层的都截图给您贴出来,这里是model里定义的类型

这里是dal层要将所有字段实体化的地方

这是它给出的提示

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 11:19

@噜灬噜噜: 人家说不能隐式转换你就显示转换噻

model.F_FLOWSHEET = (byte[])row["F_FLOWSHEET"]

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 11:21

@刘宏玺: = =   好的吧   我刚才是这样试的byte[]row["F_flowsheet"] 提示byte[]无效表达式。。。。感谢

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 11:23

@噜灬噜噜: 我感觉你快要实现了!

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 11:24

@刘宏玺: 正在试,现在的情况是添加时,添加的方法model.F_flowsheet接收不到值了

下面的上传图片方法里,是有数据的,file里也是有数据的,但是这里定义的session["imageUrl"]没有提示,断点已经走过去了,但下面不会提示它有没有数据,根本就不显示这个session["imageUrl"],不管是让session[imageUrl]=te或者fr都是不行的,自我感觉,上面的model.F_flowsheet应该等于这个file- -

求解。。。。。真的尴尬

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:01

@噜灬噜噜: 你的执行顺序是啥?要先执行下面的,在执行上面的才行

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:20

@刘宏玺: 执行的顺序就是先走上传图片的方法,然后点击保存,再走InsertType这个方法,这执行的顺序没有错吧。。。

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:21

@噜灬噜噜: 那理论上是没问题,但是你为啥要是用session保存中间数据呢?直接把te 传过去不就得了

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:23

@刘宏玺: 这是两个方法  te没办法直接穿过去吧

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:26

@噜灬噜噜: 你就不会直接传过去?还是你在前台调用的两个方法?

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:28

@刘宏玺: 前台调用的应该是两个方法。一个点击上传按钮然后开始上传,然后先走这个Uplodimage,上传成功后,点击保存,再走insertType这个方法

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:32

@噜灬噜噜: 那说明session控制的不对

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:34

@刘宏玺: 意思是session写的方法不对吗?(byte[])session("imageUrl")在Uploadimage里写是会提示错误的,您有什么好的办法吗?

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:37

@噜灬噜噜: 好的方法就是不适用session 你在Uploadimage方法中返回保存的文件地址,然后InsertType的时候把这个文件地址加上,然后在通过文件地址解析成二进制流再保存数据库就实现了

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:41

@刘宏玺: 麻烦给个实例,void类型要如何才能返回这个地址呢?

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:45

@噜灬噜噜: 那就不能使用void类型了噻,要是你能搞定session的问题到也不用这个改造!

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:46

@刘宏玺: 这就很尴尬了-_-,我不敢保证如果把void换成别的类型会不会出事情

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:49

@噜灬噜噜: 肯定不会出问题的,放心吧

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:50

@刘宏玺: 好的,待会我回去改改,现在在吃饭。。。真的是麻烦您了,方便加一下QQ吗?

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 12:56

@噜灬噜噜: 840147352

刘宏玺 | 园豆:14020 (专家六级) | 2016-11-04 12:56

@刘宏玺: 麻烦验证一下,QQ是1354223253

噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 13:19
其他回答(2)
0

到处乱写大buffer总要搞崩服务器。

既然是binary你就需要把这文件全读出来fileBin = File.ReadAllBytes(),并将sql中这个bin字段赋值fileBin即可。

顺道说一下,图片就是文件,计算机都是二进制,都基于二进制。

这种方式是很劣质的方式,仅用过一次——都因为没什么并发,只是为过检,现成的垃圾数据表。

——你这里如果只保存数据库就不要在本地去干了,接收网络流的时候写到内存就行了,然后将内存buffer刷到该字段即可。

收获园豆:10
花飘水流兮 | 园豆:13617 (专家六级) | 2016-11-04 10:06

您说的好高深- -,大致的意思就是在这里获取图片路径时,将方法filestream换成fileBin = File.ReadAllBytes()是吗?下面从byte[]开始,不变吗?纯菜鸡,望见谅、

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 10:13

@噜灬噜噜: 

拿去抄改,虽然是mvc的差不多——

public ActionResult Image(int vehicleId)
{
byte[] foundBuff = null;
foundBuff = Table.Where(t => t.VehicleID == vehicleId).Select(f => f.Photo).FirstOrDefault();
//try{foundBuff = Table.Where(t => t.VehicleID == vehicleId).Select(f => f.Photo).FirstOrDefault();}catch (Exception){}
if (foundBuff == null)
{
var createNew = System.Drawing.Image.FromFile(Server.MapPath("~/img/nophoto.fw.png"));
var stream = new MemoryStream();
createNew.Save(stream,System.Drawing.Imaging.ImageFormat.Png);
foundBuff = stream.ToArray();
}
var converter = new ImageConverter();
var image = (Image)converter.ConvertFrom(foundBuff);
return new ImageResult()
{
Image = image,
ImageFormat = System.Drawing.Imaging.ImageFormat.Png
};
}

支持(0) 反对(0) 花飘水流兮 | 园豆:13617 (专家六级) | 2016-11-04 10:18

@花飘水流兮: 您的代码,我放在我的mvc里试了一下,Table点不出来where,imageresult也无法定义。。。。  不清楚是什么原因

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 10:31
0

好好的数据库保存什么图片,你保存个链接不就完了,你这图片塞oracle里就要上blob,oracle中用blob麻烦的要死。

收获园豆:10
Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 14:54

但是没有办法,我只是后台管理,前台还有一个展示,展示的时候也要从数据库获取图片,如果只是一个链接或者一个路径,前台是获取不到这个图片的,只能转成二进制。。。。

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 15:24

您说的没错   看上面的截图,数据库的字段就是blob类型的

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 15:26

@噜灬噜噜: 为什么不能?最简单的办法就是堆一台文件服务器,开个iis提供给出来http访问图片就完了。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 15:27

@Daniel Cai: = =    您说的不太明白, 本人太菜了,是个新手

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 15:32

@噜灬噜噜: 按照你前面代码逻辑,上传了后先把文件落地到本地,然后再读取文件再写入到db。

你只需要把文件落地到另一台服务器上(有读写共享),然后记录下保存的文件名(或文件相对地址)回写到db中即完成了这次上传操作。

任意地方需要加载这条数据的时候,只需要把db中记录下来的文件名(或文件相对地址)根据实际部署情况拼接成一个http的url就可以在页面上进行呈现了。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 15:36

@Daniel Cai: 我现在上传成功后,在数据显示的是system.byte[],而不是一张图片,这叫上传成功吗?

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 15:42

@Daniel Cai: 以前我上传成功后,存入的是本地路径,但是,我老大的前台读不到,这就很尴尬,这个system.byte[]前台也是读不到的,他的前台好像只能读取像我刚才说的,数据库里就可以看到图片,如果数据库里都显示不了图片,他的前台好像就读不到图片。。。。。。

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 15:47

@噜灬噜噜: 假设我内网如下

A 外网站点服务器(内网ip:a)

B 后台服务(内网ip:b)

C 文件服务器(内网ip:c,外网ip:c1)

当先从B上传后,文件直接落地到C上,然后记录文件名xxx.jpg到db中,当从A读取时,直接拼接出来http://c1/.../xxx.jpg就可以了。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 15:49

@噜灬噜噜: 显示出来为system.byte[]是因为你对byte数组做了tostring操作,按照你的思路则应该是把整个byte数组塞给blob后去execute。

按照我的思路就是你可以抛掉这些byte数组,直接给一个url就完了。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 15:51

@Daniel Cai: 额  您说的我明白,您看这里这是不是证明,它已经转换成二进制了?

是不是这里的sql语句有问题,然后接收成system.byte[]了?

另外  我想问一下 这种后台上传图片然后到数据库能够显示成这样的  能不能实现?

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 16:01

@噜灬噜噜: 能,但blob字段的insert代码不是这么写的,这个地方要起个事务,然后创建一个空的blob对象,把byte数组塞进去,然后通过参数化sql提交。反过来看你最前面的代码,你的实现本身就有很大问题,你把byte数组塞到session中算什么事?这样随便上传几个,你session服务器或者你w3wp进程不撑爆?

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 16:24

@Daniel Cai: 现在我用的不是session了,因为它好像已经撑爆了,model.F_FLOWSHEET根本就得不到值,你说这种效果可以实现,但insert不是这么写的 需要起一个事务和参数化sql 能给个实例吗?我对oracle真是一点都不懂,以前用的sqlserver  保存一个路径就可以了,但这里好像不是那样简单的

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 16:28

@噜灬噜噜: 说实话,oracle中blob,clob我都是向来绕着走的,就像我前面说的,这种执行写起来相当蛋疼,如果你非要这样做的话你可以搜一下blob insert中和ado.net相关的信息。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 16:31

@噜灬噜噜: 你这里也说了,在sqlserver中保存一个路径就完了,为什么你用oracle就不能保存一个路径呢?这样实现起来会简单很多。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 16:32

@Daniel Cai: 说实话,我也不想这么搞,但是我得适应我老大的前台页面= =     多谢给的提醒,让我不至于瞎搞

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 16:32

@Daniel Cai:刚才问您的,那个二进制是不是已经转换成功了呢?

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 16:33

@噜灬噜噜: 建议你和他商量下,按照我说方案来,这样两边都轻松,而且就算他以前是直接从blob中读取的图片显示出来这种实现改成我说的这样也简单。(不过话说他之前真的是从blob中读取图片字节数组然后再输出么?这样做是不是蛋疼的太厉害了)

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 16:35

@Daniel Cai: 那就不清楚了,我现在看到的就是,只有数据库的blob字段显示出来图片,他的前台才能够展示,路径或者system.byte[]都是不行的。。。。

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 16:36

@噜灬噜噜: 你debug下,看下你准备带到blob字段是不是一个byte数组类型就知道了。这个地方没走过你代码我不清楚。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 16:38

@Daniel Cai: 我之前的这个截图,显示的是model.F_FLOWSHEET里的是byte数组类型,但通过sql添加的时候就变成字符串:system.byte[]了,不知道我说的对不对- -

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 16:42

@噜灬噜噜: 你string.format肯定变那样了啊。你那里要用参数化来执行

IDataParameter

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 16:44

@Daniel Cai: 不懂= =

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 16:54

@噜灬噜噜: string.format最后带进去的参数都会调用其tostring方法,而byte数组的tostring就返回其typename,所以你db里面肯定记的是字面的system.byte[]。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 16:59

@Daniel Cai: 这个我清楚了,我不明白的是怎么给他参数化是在字段前面加引号(:)吗?

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 17:01

@噜灬噜噜: 这个建议你找msdn上看下,大概逻辑就是把你的实参通过dataparameter塞给command,最后去执行。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-11-04 17:06

@Daniel Cai: 我找到一个这个:http://www.cnblogs.com/aito/archive/2010/08/25/1808569.html

支持(0) 反对(0) 噜灬噜噜 | 园豆:21 (初学一级) | 2016-11-04 17:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册