你的位置:首页 > ASP.net教程

[ASP.net教程]图片分布式存储


优点:图片分布式存储主要解决服务器存储压力,以及提高查询速度;

方案:用户发起上传请求,在发起请求的服务器中,根据图片信息表中的数据查找可用的服务器,此时可能查找多台服务器,那么根据从状态表筛选出可用的图片服务器集合记作C,并获取集合的总记录数N。然后用随机函数产生一个随机数R1并用R1与N进行取余运算记作I=R1%N。则C[I]即为要保存图片的图片服务器,选择可用的服务器,然后使用WebClient发起请求,在可用的服务器中存储图片,具体如下:

解决步骤:

          1.在数据库中新建两个表分别是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();

//从状态表筛选出可用的图片服务器集合记作C,并获取集合的总记录数N。然后用随机函数产生一个随机数R1并用R1与N进行取余运算记作I=R1%N。则C[I]即为要保存图片的图片服务器
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);//设置当前流所在的位置:第一个参数是相对于第二个参数指定的位置的相对偏移位置。

return buffer;
}

3.新建两个web应用程序 分别代表分布在不同服务器上的应用程序
  并在一般处理程序下添加如下方法

    

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";

string imgExt = context.Request["ext"];//获取文件扩展名

string serverId = context.Request["serverId"];//获取数据库中表ImageServerInfo的标识

string imgNewName = Guid.NewGuid().ToString();//用Guid为新的文件重命名

string path = "/ImgFileUpload/" + DateTime.Now.Year + "/" + DateTime.Now.Month + "/" + DateTime.Now.Day + "/";//按照每年每月每天创建新的文件夹 避免因为大量的图片文件在同一个文件夹中,造成打开文件卡死现象

Directory.CreateDirectory(Path.GetDirectoryName(context.Server.MapPath(path)));//创建文件夹 此时类Directory内部已经判断是否存在该文件无需再次判断

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.分别启动相应的应用程序 上传文件并测试