zoukankan      html  css  js  c++  java
  • 图片文件分布式存储方案设计模式(c#--sqlserver)

    1、为了降低web服务器的压力,申请了2台文件服务器,用来存放图片文件。但是两台文件服务器如何让程序自己选择呢?

    于是我用了一个算法,思路如下:

    从状态表筛选出可用的图片服务器集合记作C,并获取集合的总记录数N,

    然后用随机函数产生一个随机数R1与N进行取余运算记作I=R1%N,则c[I]即为要保存图片服务器。

    然后我开始设计两个表,一个是图片文件服务器表、一个是图片信息表。1对多的关系。

    表1:ImageServerInfo  图片文件服务器表

    表2:ImageInfo   图片信息表

    表脚本入下:

    USE [MyImageServer]
    GO
    
    /****** Object:  Table [dbo].[ImageServerInfo]    Script Date: 07/04/2020 21:17:15 ******/
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [dbo].[ImageServerInfo](
        [ServerId] [int] IDENTITY(1,1) NOT NULL,  --服务器id
        [ServerName] [nvarchar](32) NOT NULL,     --图片服务器名称
        [ServerUrl] [nvarchar](100) NOT NULL,     --图片服务器
        [PicRootPath] [nvarchar](100) NOT NULL,   --图片存储的物理路径
        [MaxPicAmount] [int] NOT NULL,            ---图片存储的上限
        [CurPicAmount] [int] NOT NULL,            --图片当前存储的数量
        [FlgUsable] [bit] NOT NULL,               ---图片服务器的状态
     CONSTRAINT [PK_ImageServerInfo] PRIMARY KEY CLUSTERED 
    (
        [ServerId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    ----------------
    ----------------
    ----------------
    ----------------

    USE [MyImageServer]
    GO

    /****** Object: Table [dbo].[ImageInfo] Script Date: 07/04/2020 21:16:57 ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO

    CREATE TABLE [dbo].[ImageInfo](
    [Id] [int] IDENTITY(1,1) NOT NULL,       ---该具体的id
    [ImageName] [nvarchar](100) NOT NULL,    ---图片的路径名称
    [ImageServerId] [int] NOT NULL,          ---存储到哪台服务器的id
    CONSTRAINT [PK_ImageInfo] PRIMARY KEY CLUSTERED
    (
    [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    ALTER TABLE [dbo].[ImageInfo] WITH CHECK ADD CONSTRAINT [FK_ImageInfo_ImageServerInfo] FOREIGN KEY([ImageServerId])
    REFERENCES [dbo].[ImageServerInfo] ([ServerId])
    GO

    ALTER TABLE [dbo].[ImageInfo] CHECK CONSTRAINT [FK_ImageInfo_ImageServerInfo]
    GO

     

     表结构建立好之后,开始打开 Microsoft Visual Studio 软件,新建一个 ImageSystem 解决方案,这里用来模拟web服务器。

       1、web层我建立的是MVC进行演示 ImageSystem.WebApp。

       2、然后建立一个实体层ImageSystem.Model 用来引用 Model1.edmx 作为EntityFramework做数据库连接。

       3、建立两个空Web,用来做图片文件服务器。命名为 ImageSystem.ImageServeOne、ImageSystem.ImageServeTwo

       4、项目结构如图:

              

     web应用服务器的Controllers层的HomeController代码如下:

    using ImageSystem.Model;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.Mvc;
    
    namespace ImageSystem.WebApp.Controllers
    {
        public class HomeController : Controller
        {
            MyImageServerEntities db = new MyImageServerEntities();
            // GET: Home
            public ActionResult Index()
            {
                return View();
            }
            public ActionResult FileUpload()
            {
                HttpPostedFileBase file = Request.Files["fileUp"];
                if (file != null)
                {
                    string fileName = Path.GetFileName(file.FileName);
                    string fileExt = Path.GetExtension(fileName);
                    if (fileExt == ".jpg" || fileExt == ".png" || fileExt == ".gif")
                    {
                        //从状态表筛选出可用的图片服务器集合记作C,并获取集合的总记录数N,然后用随机函数产生一个随机数R1与N进行取余运算记作I=R1%N,则c[I]即为要保存图片服务器
                     var list=db.ImageServerInfo.Where(a => a.FlgUsable == true).ToList();
                        int count = list.Count();
                        Random random = new Random();
                        int r = random.Next();
                        int i = r % count;
                        ImageServerInfo imageServiceInfo = list[i];//筛选出一个服务器
                        WebClient client = new WebClient();
                        string address = "http://" + imageServiceInfo.ServerUrl + "/FileUp.ashx?serverId=" + imageServiceInfo.ServerId + "&ext=" + fileExt;
                        client.UploadData(address, StreamToByte(file.InputStream));
                        return Content("文件上传成功!");
                    }
                    else
                    {
                        return Content("文件类型错误!!");
                    }
                }
                else
                {
                    return Content("文件不能为空!!");
                }
            }
    
            private byte[] StreamToByte(Stream inputStream)
            {
                byte[] buffer = new byte[inputStream.Length];
                inputStream.Read(buffer, 0, buffer.Length);
                inputStream.Seek(0, SeekOrigin.Begin);
                return buffer;
            }
            public ActionResult ShowImage()
            {
                var list = db.ImageServerInfo.Where(a => a.FlgUsable == true).ToList();
                ViewData["list"] = list;
                return View();
                  
            }
        }
    }

    HomeController对应的view视图Index页面如下:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>分布式图片上传</title>
    </head>
    <body>
        <div> 
                  <form method="post" action="/Home/FileUpload" enctype="multipart/form-data">
                      <input type="file" name="fileUp"  />
                      <input type="submit"  value="上传图片" />
                  </form>
        </div>
    </body>
    </html>

    HomeController对应的view视图ShowImage页面如下:

    这个页面是辅助查看上传的图片进行展示

    @{
        Layout = null;
    }
    @using ImageSystem.Model
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>ShowImage</title>
    </head>
    <body>
        <div>
            @if (ViewData["list"] != null)
            {
                foreach (var ImageServerInfo in (List<ImageServerInfo>)ViewData["list"])
                {
                    foreach (var ImageInfo in ImageServerInfo.ImageInfo)
                    {
                        <img src="@string.Format("http://{0}{1}",ImageServerInfo.ServerUrl,ImageInfo.ImageName)" alt="" width="200px" height="170px" /> 
    @ImageServerInfo.ServerName
    @ImageServerInfo.ServerUrl @ImageInfo.ImageName @ImageInfo.ImageServerId <br /> } } } </div> </body> </html>

    以上便是模拟的web服务器,下面插入Web图片文件服务器的代码,我只展示一台,另外一台除了ip端口不同,代码都一样的:

    在图片文件服务器根目录建立images文件夹,然后新增一个FileUp.ashx一般处理程序,用来接收图片的字节数组,一般处理程序的代码如下:

    using ImageSystem.Model;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web;
    
    namespace ImageSystem.ImageServeTwo
    {
        /// <summary>
        /// FileUp 的摘要说明
        /// </summary>
        public class FileUp : IHttpHandler
        {
    
            public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "text/plain";
                string ext = context.Request["ext"];
                int serverId = int.Parse(context.Request["serverId"]);
                string dir = "/images/" + DateTime.Now.Year + "/" + DateTime.Now.Month + "/" + DateTime.Now.Day + "/";
                Directory.CreateDirectory(Path.GetDirectoryName(context.Request.MapPath(dir)));
                string newfileName = Guid.NewGuid().ToString();
                string fullDir = dir + newfileName + ext;
                using (FileStream stream = File.OpenWrite(context.Request.MapPath(fullDir)))
                {
                    //将文件流写到指定的文件下
                    context.Request.InputStream.CopyTo(stream);
                    MyImageServerEntities db = new MyImageServerEntities();
                    ImageInfo imageInfo = new ImageInfo();
                    imageInfo.ImageName = fullDir;
                    imageInfo.ImageServerId = serverId;
                    db.ImageInfo.Add(imageInfo);
                    db.SaveChanges();
                }
            }
            public bool IsReusable
            {
                get
                {
                    return false;
                }
            }
        }
    }

    这个处理程序会把接收的图片存储到服务器上,并且把途径插入数据库的表中,这里要引用一下EF实体层的ImageSystem.Model

    ,此时,就可以启动3个项目了,然后主web服务器上传图片,此时就根据随机算法存储图片。

     后期,如公司继续增加图片文件服务器,你只需要在数据库中加一个ip地址就行了,然后再部署一台文件服务器,主web服务器无需重新发版,就可热使用。

    以上便是利用C#和sqlserver数据库做的图片文件分布式存储方案设计模式!

  • 相关阅读:
    JavaScript中的prototype
    SQL 时间格式转换
    ASP.NET MVC自定义视图引擎ViewEngine 创建Model的专属视图
    JavaScript事件使用指南
    30行代码实现JavaScript中的MVC
    JavaScript中this指针指向的彻底理解
    JavaScript 中的命名空间
    C#嵌套类型
    C# 为枚举创建新方法
    Lambda 表达式
  • 原文地址:https://www.cnblogs.com/zcc666/p/13236729.html
Copyright © 2011-2022 走看看