1. 程式人生 > 實用技巧 >圖片檔案分散式儲存方案設計模式(c#--sqlserver)

圖片檔案分散式儲存方案設計模式(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(,) 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資料庫做的圖片檔案分散式儲存方案設計模式!