因为对应用场景不是特别明确,暂时就用wcf做一个可以上传和下载的功能来管理族库。
首先添加上传下载的接口:
[ServiceContract]
public interface IFileService
{
//上传文件
[OperationContract]
UpFileResult UpLoadFile(UpFile filestream);
//下载文件
[OperationContract]
DownFileResult DownLoadFile(DownFile downfile);
}
[MessageContract]
public class DownFile
{
[MessageHeader]
public string FileName { get; set; }
}
[MessageContract]
public class UpFileResult
{
[MessageHeader]
public bool IsSuccess { get; set; }
[MessageHeader]
public string Message { get; set; }
}
[MessageContract]
public class UpFile
{
[MessageHeader]
public long FileSize { get; set; }
[MessageHeader]
public string FileName { get; set; }
[MessageBodyMember]
public Stream FileStream { get; set; }
}
[MessageContract]
public class DownFileResult
{
[MessageHeader]
public long FileSize { get; set; }
[MessageHeader]
public bool IsSuccess { get; set; }
[MessageHeader]
public string Message { get; set; }
[MessageBodyMember]
public Stream FileStream { get; set; }
}
然后实现接口:
public class FileService : IFileService
{
public UpFileResult UpLoadFile(UpFile filedata)
{
UpFileResult result = new UpFileResult();
string path = System.AppDomain.CurrentDomain.BaseDirectory + @"\service\";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
byte[] buffer = new byte[filedata.FileSize];
FileStream fs = new FileStream(path + filedata.FileName, FileMode.Create, FileAccess.Write);
int count = 0;
while ((count = filedata.FileStream.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, count);
}
//清空缓冲区
fs.Flush();
//关闭流
fs.Close();
result.IsSuccess = true;
return result;
}
//下载文件
public DownFileResult DownLoadFile(DownFile filedata)
{
DownFileResult result = new DownFileResult();
string path = System.AppDomain.CurrentDomain.BaseDirectory + @"\service\" + filedata.FileName;
if (!File.Exists(path))
{
result.IsSuccess = false;
result.FileSize = 0;
result.Message = "服务器不存在此文件";
result.FileStream = new MemoryStream();
return result;
}
Stream ms = new MemoryStream();
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
fs.CopyTo(ms);
ms.Position = 0; //重要,不为0的话,客户端读取有问题
result.IsSuccess = true;
result.FileSize = ms.Length;
result.FileStream = ms;
fs.Flush();
fs.Close();
return result;
}
}
开启服务:
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(FileService));
host.Open();
Console.WriteLine("开启服务");
Console.ReadKey();
}
配置net.tcp绑定,NetTcpBinding用于跨机器交互表现的效果较好,所以这里用这个绑定。对应的环境设置:
这其中有个重要的一点是,客户端不能用App.config来配置服务环境,所以这里需要用代码来实现配置,这点非常重要,不然会报错,实现不了。根据服务端来实现客户端的绑定配置:
Uri baseUri = new Uri("net.tcp://localhost/mysever");
EndpointAddress epaddr = new EndpointAddress(baseUri);
NetTcpBinding binding = new NetTcpBinding();
binding.Name = "MyTcpBinding";
binding.MaxBufferSize = 2147483647;
binding.MaxReceivedMessageSize = 2147483647;
binding.SendTimeout = new TimeSpan(0,30,0);
binding.TransferMode = TransferMode.Streamed;
binding.Security.Mode = SecurityMode.None;
然后客户端还需要写接口,这个跟服务端一样即可。
wpf页面的后台完整代码:
IFileService m_instance;
public UpDateFileView()
{
InitializeComponent();
Uri baseUri = new Uri("net.tcp://localhost/mysever");
EndpointAddress epaddr = new EndpointAddress(baseUri);
NetTcpBinding binding = new NetTcpBinding();
binding.Name = "MyTcpBinding";
binding.MaxBufferSize = 2147483647;
binding.MaxReceivedMessageSize = 2147483647;
binding.SendTimeout = new TimeSpan(0,30,0);
binding.TransferMode = TransferMode.Streamed;
binding.Security.Mode = SecurityMode.None;
m_instance = ChannelFactory.CreateChannel(binding, epaddr);
}
private void updataFile_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog Fdialog = new OpenFileDialog();
if (Fdialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
using (Stream fs = new FileStream(Fdialog.FileName, FileMode.Open, FileAccess.Read))
{
this.filepath.Text = Fdialog.SafeFileName;
UpFileResult result = m_instance.UpLoadFile(new UpFile() {FileName= Fdialog.SafeFileName,FileSize= fs.Length,FileStream= fs});
if (result.IsSuccess == true)
{
System.Windows.MessageBox.Show("上传成功!");
}
else
{
System.Windows.MessageBox.Show("上传失败!");
}
}
}
}
private void downloadFile_Click(object sender, RoutedEventArgs e)
{
string filename = this.filename.Text;
string path = System.AppDomain.CurrentDomain.BaseDirectory + @"\client\";
Stream filestream = new MemoryStream();
//long filesize = m_instance.DownLoadFile(filename, out issuccess, out message, out filestream);
DownFileResult filesize = m_instance.DownLoadFile(new DownFile() { FileName = filename });
if (filesize.IsSuccess)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
byte[] buffer = new byte[filesize.FileSize];
FileStream fs = new FileStream(path + filename, FileMode.Create, FileAccess.Write);
int count = 0;
while ((count = filestream.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, count);
}
//清空缓冲区
fs.Flush();
//关闭流
fs.Close();
System.Windows.MessageBox.Show("下载成功!");
}
else
{
System.Windows.MessageBox.Show("下载失败!");
}
}
这样就实现了客户端的截面逻辑。
最后实现一下 IExternalCommand接口即可。
namespace Revit
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)]
public class Class1 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UpDateFileView view = new UpDateFileView();
view.ShowDialog();
return Result.Succeeded;
}
}
}
当然还有许多工作要做,比如上传路径,限定上传文件的后缀名,上传的族文件的管理,用户名及密码的验证等等,这些细节处理好后,就可以实现族库管理的功能。