FastDfs是一个开源的轻量级分布式文件系统,其原理可以查看http://blog.chinaunix.net/uid-20196318-id-4058561.html,然后部署安装部分可参考http://blog.csdn.net/poechant/article/details/7209313,这里只是简单的说明下在C#中如何使用FastDfs。
首先是通过Nuget下载dll,具体地址为https://www.nuget.org/packages/FastDFS/
然后可以通过程序来设置相关Tracker服务器地址及群组信息,也可以通过配置文件来配置
通过代码方式的话是如下方式
new FastDfsConfig
{
//FastDfsServer =...,
//GroupName =...
};
而通过配置文件方式的话,需要在配置文件的configSections节点中添加如下配置
其中fastdfs为默认节点名,当然name也可以指定为其它值,然后实际配置如下
然后在代码中通过下列代码来初始化
Config = FastDfsManager.GetConfigSection();
ConnectionManager.InitializeForConfigSection(Config);
FastDfs相关的操作代码主要集中在FastDFSClient类中,然后实际项目中我们只是用到了UploadFile,所以也就只是简单地做了个封装
using FastDFS.Client;
using FastDFS.Client.Config;
using System.IO;
public static class FastDfsHelper
{
///
/// Dfs文件
///
public class FastDfsFile
{
///
/// Dfs群组名
///
public string GroupName { get; private set; }
///
/// Dfs文件路径(包含文件名)
///
public string FileName { get; private set; }
public FastDfsFile(string groupName, string fileName)
{
if (string.IsNullOrWhiteSpace(groupName))
{
throw new ArgumentNullException("groupName can not be null.");
}
if (string.IsNullOrWhiteSpace(fileName))
{
throw new ArgumentNullException("fileName can not be null.");
}
this.GroupName = groupName;
this.FileName = fileName;
}
///
/// 获取文件在服务器上访问的路径(不包含域名部分)
///
///
public override string ToString()
{
return string.Format("{0}/{1}", this.GroupName, this.FileName);
}
}
static readonly FastDfsConfig Config;
static FastDfsHelper()
{
Config = FastDfsManager.GetConfigSection();
ConnectionManager.InitializeForConfigSection(Config);
}
///
/// 上传文件
///
/// 文件数组
///
///
public static FastDfsFile Upload(byte[] contentByte, string fileExt)
{
var node = FastDFSClient.GetStorageNode(Config.GroupName);
return new FastDfsFile(Config.GroupName, FastDFSClient.UploadFile(node, contentByte, fileExt.Trim('.')));
}
///
/// 上传文件
///
/// 文件流
///
///
public static FastDfsFile Upload(Stream stream, string fileExt)
{
using (stream)
{
byte[] contentByte = new byte[stream.Length];
stream.Read(contentByte, 0, contentByte.Length);
return Upload(contentByte, fileExt);
}
}
///
/// 将数据流读取成byte数组,并在读取完成后将流当前位置设置为0
///
///
///
public static byte[] StreamToBytes(Stream stream)
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
// 设置当前流的位置为流的开始
stream.Seek(0, SeekOrigin.Begin);
return bytes;
}
///
/// 移除文件
///
///
///
public static void Remove(string groupName, string fileName)
{
FastDFSClient.RemoveFile(groupName, fileName);
}
}
然后因为我们主要是上传图片,所以这里还从网上找了段压缩的代码,然后简单的调整了下
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
public static class ImageHelper
{
///
/// JPG编码解码器信息,为null表示未安装
///
public static readonly ImageCodecInfo JPEGICIinfo;
static ImageHelper()
{
JPEGICIinfo = GetJPEGICIinfo();
}
///
/// 图片压缩并获得压缩后的数据流,如果出现异常则返回null,注意使用完之后释放
///
/// 原始图片内容
/// 压缩后的最大高度
/// 压缩后的最大宽度
/// 压缩质量 1-100
///
public static Stream GetPicThumbnail(byte[] imgByte, int dHeight, int dWidth, int flag)
{
using (var sStream = new MemoryStream(imgByte))
{
Image iSource = Image.FromStream(sStream);
ImageFormat tFormat = iSource.RawFormat;
//按比例缩放
var zSize = GetZoomSize(new Size(iSource.Width, iSource.Height), dWidth, dHeight);
Bitmap ob = new Bitmap(zSize.Width, zSize.Height);
using (Graphics g = Graphics.FromImage(ob))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(iSource, new Rectangle(0, 0, zSize.Width, zSize.Height), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
}
MemoryStream rStream = new MemoryStream();
try
{
if (JPEGICIinfo != null)
{
ob.Save(rStream, JPEGICIinfo, GetEncoderParameters(flag));
}
else
{
ob.Save(rStream, tFormat);
}
rStream.Position = 0;
}
catch
{
rStream.Dispose();
rStream = null;
}
finally
{
iSource.Dispose();
ob.Dispose();
}
return rStream;
}
}
private static Size GetZoomSize(Size sSize, int dWidth, int dHeight)
{
int sW = sSize.Width, sH = sSize.Height;
//按比例缩放
if (sSize.Width > dHeight || sSize.Width > dWidth) //将**改成c#中的或者操作符号
{
if ((sSize.Width * dHeight) > (sSize.Height * dWidth))
{
sW = dWidth;
sH = (dWidth * sSize.Height) / sSize.Width;
}
else
{
sH = dHeight;
sW = (sSize.Width * dHeight) / sSize.Height;
}
}
return new Size(sW, sH);
}
private static ImageCodecInfo GetJPEGICIinfo()
{
ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo jpegICIinfo = null;
for (int x = 0; x < arrayICI.Length; x++)
{
if (arrayICI[x].FormatDescription.Equals("JPEG"))
{
jpegICIinfo = arrayICI[x];
break;
}
}
return jpegICIinfo;
}
private static EncoderParameters GetEncoderParameters(int flag)
{
//以下代码为保存图片时,设置压缩质量
EncoderParameters ep = new EncoderParameters();
long[] qy = new long[1];
qy[0] = flag;//设置压缩的比例1-100
EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
ep.Param[0] = eParam;
return ep;
}
}
简单的使用代码如下
string localPath = @"E:\demoPic\03.jpg";
string newPath1 = @"E:\demoPic\NN03.jpg";
var imgByte = File.ReadAllBytes(localPath);
//图片压缩
var stream = ImageHelper.GetPicThumbnail(imgByte, 500, 500, 70);
if (stream != null)
{
using (stream)
{
byte[] bytes = FastDfsHelper.StreamToBytes(stream);
//文件上传
var file = FastDfsHelper.Upload(stream, Path.GetExtension(localPath).Trim('.'));
Console.WriteLine(file);//file.ToString()结果就为排除fastDfs访问域名后完整的图片访问路径
File.WriteAllBytes(newPath1, bytes);//本地存储以便与上传到Dfs的文件进行比较
}
}