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(,) NOT NULL, --服务器id
[ServerName] [nvarchar]() NOT NULL, --图片服务器名称
[ServerUrl] [nvarchar]() NOT NULL, --图片服务器
[PicRootPath] [nvarchar]() 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, , buffer.Length);
inputStream.Seek(, 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服务器上传图片,此时就根据随机算法存储图片。

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

图片文件分布式存储方案设计模式(c#--sqlserver)的更多相关文章

  1. IIs 网站应用程序与虚拟目录的区别及高级应用说明(文件分布式存储方案)

    原文 IIs 网站应用程序与虚拟目录的区别及高级应用说明(文件分布式存储方案) 对于IIS网站,大伙用的比较多,就不啰嗦了.   今天和说说大伙比较少使用的"IIS应用程序”和虚拟目录的区别 ...

  2. lucene大索引文件分布式存储方案

    这几天实现了个Lucene分布式检索的模块,采用的分布式方案是将数据分块,分别生成N个索引文件,放到N个节点上运行.检索时,对每一个节点发出查询请求,将N个节点返回的结果归并,然后生成一个新的结果.如 ...

  3. MongoDb gridfs-ngnix文件存储方案 - 图片

    http://www.cnblogs.com/wintersun/p/4622205.html 在各类系统应用服务端开发中,我们经常会遇到文件存储的问题. 常见的磁盘文件系统,DBMS传统文件流存储. ...

  4. MongoDb gridfs-ngnix文件存储方案

          在各类系统应用服务端开发中,我们经常会遇到文件存储的问题. 常见的磁盘文件系统,DBMS传统文件流存储.今天我们看一下基于NoSQL数据库MongoDb的存储方案.笔者环境 以CentOS ...

  5. Apache日志不记录图片文件设置方法和来源日志的配置

    Apache日志不记录图片文件设置方法 <FilesMatch "\.(ico|gif|jpg|swf)">SetEnv IMAG 1</FilesMatch&g ...

  6. C#技术分享【PDF转换成图片——13种方案】(2013-07-25重新整理)

    原文:C#技术分享[PDF转换成图片--13种方案](2013-07-25重新整理) 重要说明:本博已迁移到 石佳劼的博客,有疑问请到 文章新地址 留言!!! 写在最前面:为了节约大家时间,撸主把最常 ...

  7. Hadoop小文件存储方案

    原文地址:https://www.cnblogs.com/ballwql/p/8944025.html HDFS总体架构 在介绍文件存储方案之前,我觉得有必要先介绍下关于HDFS存储架构方面的一些知识 ...

  8. EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象

    EF+LINQ事物处理   在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...

  9. Android从本地选择图片文件转为Bitmap,并用zxing解析Bitmap

    如何从本地选择图片文件 使用Intent调用系统相册后,onActivityResult函数返回的是Uri格式的路径 /** * 打开系统相册 */ private void openSysAlbum ...

随机推荐

  1. java实现坐标

    * 已知平面上若干个点的坐标. 需要求出在所有的组合中,4 个点间平均距离的最小值(四舍五入,保留 2 位小数). 比如有 4 个点:a,b,c,d,则平均距离是指:ab, ac, ad, bc, b ...

  2. PAT A+B和C

    题目描述 给定区间[-2的31次方, 2的31次方]内的3个整数A.B和C,请判断A+B是否大于C. 输入描述: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测试用例,每组 ...

  3. iOS - 多线程——GCD

    什么是GCD           Grand Central Dispatch(强大的调度器),是一个C语言API:           作用:多核并行运算的解决方案:  GCD中有2个核心概念    ...

  4. 死啃了String源码之后

    Java源码之String 说在前面: 为什么看源码: 最好的学习的方式就是模仿,接下来才是创造.而源码就是我们最好的模仿对象,因为写源码的人都不是一般的人,所以用心学习源码,也就可能变成牛逼的人.其 ...

  5. 被迫重构代码,这次我干掉了 if-else

    本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近公司貌似融到资了!开始发了疯似的找渠道推广,现在终于明白为啥前一段大肆的招人了,原来是在下一盘大棋,对员工总的来 ...

  6. php的ts和nts选择

    TS(Thread-Safety)即线程安全,多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据 ...

  7. 【分区】使用 GPT 分区表分区并格式化 (非 FreeBSD 系统)

    新购买的 Linux 云服务器,由于数据盘未做分区和格式化,无法使用. 注意: 数据盘中的数据在格式化后将全部被清空.请在格式化之前,确保数据盘中没有数据或已对重要数据进行备份.为避免服务发生异常,格 ...

  8. 并行处理框架Celery的Web监控管理服务-Flower

    安装和使用 使用pip安装Flower: $ pip install flower或 pip install flower -U -i https://pypi.tuna.tsinghua.edu.c ...

  9. AlertController的使用

    UIAlertView 随着苹果上次iOS 5的发布,对话框视图样式出现在了我们面前,直到现在它都没有发生过很大的变化.下面的代码片段展示了如何初始化和显示一个带有“取消”和“好的”按钮的对话框视图. ...

  10. vim中的替换操作

    在vim中 :s(substitute)命令用于查找并替换字符串.使用方法如下: :s/<find-this>/<replace-with-this>/<flags> ...