優(yōu)點:圖片分布式存儲主要解決服務(wù)器存儲壓力,以及提高查詢速度;
方案:用戶發(fā)起上傳請求,在發(fā)起請求的服務(wù)器中,根據(jù)圖片信息表中的數(shù)據(jù)查找可用的服務(wù)器,此時可能查找多臺服務(wù)器,那么根據(jù)從狀態(tài)表篩選出可用的圖片服務(wù)器集合記作C,并獲取集合的總記錄數(shù)N。然后用隨機函數(shù)產(chǎn)生一個隨機數(shù)R1并用R1與N進行取余運算記作I=R1%N。則C[I]即為要保存圖片的圖片服務(wù)器,選擇可用的服務(wù)器,然后使用WebClient發(fā)起請求,在可用的服務(wù)器中存儲圖片,具體如下:
解決步驟:
1.在數(shù)據(jù)庫中新建兩個表分別是ImageServerInfo,ImageInfo;
表:ImageServerInfo
CREATE TABLE [dbo].[ImageServerInfo]([ServerId] [int] IDENTITY(1,1) NOT NULL,[ServerName] [nvarchar](32) NOT NULL,[ServerUrl] [nvarchar](100) 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
表:ImageInfo
CREATE TABLE [dbo].[ImageInfo]([Id] [int] IDENTITY(1,1) NOT NULL,[ImageName] [nvarchar](100) NOT NULL,[ImageServerId] [int] NOT NULL, 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
2.新建mvc項目 添加一個控制器 并添加以下方法
public ActionResult FileUpload() { HttpPostedFileBase file = Request.Files["ImgFile"];
string fileName = file.FileName;
string fileExt = Path.GetExtension(fileName);
if (fileExt == ".jpg" || fileExt == ".png") { ImageServerEntities dbContext = new ImageServerEntities();
var isiList = dbContext.ImageServerInfo.Where(x => x.FlgUsable == true).ToList();
int countN = isiList.Count();
//從狀態(tài)表篩選出可用的圖片服務(wù)器集合記作C,并獲取集合的總記錄數(shù)N。然后用隨機函數(shù)產(chǎn)生一個隨機數(shù)R1并用R1與N進行取余運算記作I=R1%N。則C[I]即為要保存圖片的圖片服務(wù)器 Random rand = new Random();
int r1 = rand.Next();
int i = r1 % countN;
ImageServerInfo isi = isiList[i];
string url = string.Format("http://{0}/FileUp.ashx?serverId={1}&ext={2}", isi.ServerUrl, isi.ServerId, fileExt);
WebClient wc = new WebClient();
wc.UploadData(url, StreamToByteArray(file.InputStream));
return Content("success"); } else { return Content("請注意文件類型!"); } }
private byte[] StreamToByteArray(Stream stream) { byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Seek(0, SeekOrigin.Begin);//設(shè)置當(dāng)前流所在的位置:第一個參數(shù)是相對于第二個參數(shù)指定的位置的相對偏移位置。
return buffer; }
3.新建兩個web應(yīng)用程序 分別代表分布在不同服務(wù)器上的應(yīng)用程序 并在一般處理程序下添加如下方法
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain";
string imgExt = context.Request["ext"];//獲取文件擴展名
string serverId = context.Request["serverId"];//獲取數(shù)據(jù)庫中表ImageServerInfo的標(biāo)識
string imgNewName = Guid.NewGuid().ToString();//用Guid為新的文件重命名
string path = "/ImgFileUpload/" + DateTime.Now.Year + "/" + DateTime.Now.Month + "/" + DateTime.Now.Day + "/";//按照每年每月每天創(chuàng)建新的文件夾 避免因為大量的圖片文件在同一個文件夾中,造成打開文件卡死現(xiàn)象
Directory.CreateDirectory(Path.GetDirectoryName(context.Server.MapPath(path)));//創(chuàng)建文件夾 此時類Directory內(nèi)部已經(jīng)判斷是否存在該文件無需再次判斷
string imgFullPath = path + imgNewName + imgExt;//拼接文件路徑
using (FileStream fs=File.OpenWrite(context.Request.MapPath(imgFullPath))) { context.Request.InputStream.CopyTo(fs);//將請求文件流拷貝到需要寫入文件的文件流
ImageServerEntities dbContext = new ImageServerEntities(); ImageInfo img = new ImageInfo() { ImageName = imgFullPath, ImageServerId=Convert.ToInt32(serverId) }; dbContext.ImageInfo.Add(img); dbContext.SaveChanges(); } }
4.分別啟動相應(yīng)的應(yīng)用程序 上傳文件并測試
新聞熱點
疑難解答