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实现微生物增殖

    微生物增殖 假设有两种微生物 X 和 Y X出生后每隔3分钟分裂一次(数目加倍),Y出生后每隔2分钟分裂一次(数目加倍). 一个新出生的X,半分钟之后吃掉1个Y,并且,从此开始,每隔1分钟吃1个Y. ...

  2. Java实现第九届蓝桥杯打印大X

    打印大X 题目描述 如下的程序目的是在控制台打印输出大X. 可以控制两个参数:图形的高度,以及笔宽. 用程序中的测试数据输出效果: (如果显示有问题,可以参看p1.png) 高度=15, 笔宽=3 * ...

  3. Android Studio自定义签名文件

    在项目多人开发的时候,如果使用到第三方框架,需要keystore的sha1值的时候,则需要共享debug签名才能进行程序调试 可以在gradle文件中配置如下选项,并且把keystore文件放到项目m ...

  4. STM32学习笔记——printf

    printf复习 当我们写printf("%d\n", 1);的时候,printf函数并不能通过C语言语法得知第二个参数是int类型.printf是一个变参函数(variadic ...

  5. ubuntu12.04 跳过grub选择

    1.修改/etc/grub.d/00_head文件. set timeout=-1 修改成 set timeout = ${GRUB_RECORDFAIL_TIMEOUT:--1} 2.修改/etc/ ...

  6. 在SpringMVC获取客户端传递的数据的方式

    在处理请求的方法中,加入相对应的形参,保证形参参数名和传递的数据的参数名保持一致,就能够自动赋值 value:当不满足赋值条件时,可以使用value属性,指定映射关系 required:设置形参是否必 ...

  7. 文本溢出后,隐藏显示"..."和margin边距重叠

    一.隐藏加省略 单行文本: overflow: hidden; white-space: nowrap; text-overflow: ellipsis; 多行文本: overflow: hidden ...

  8. Linux下常用命令(持续更新)

    l: 列举目录下的所有文件 ll: 显示详细属性 pwd: 查看当前所在完整路径 cd: 变更文件夹(变更到根目录:cd + /:变更到上级目录:cd + ..) sudo: 允许利用超级用户权限执行 ...

  9. Cookie 和 Session 关系详解

     什么是 Cookie 和 Session ? 什么是 Cookie HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在 ...

  10. NET 数据结构-单链表

    概念介绍: 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素. 链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元 ...