Revit二次開發高階應用(1)——利用wcf做簡單的族庫管理
阿新 • • 發佈:2018-11-06
因為對應用場景不是特別明確,暫時就用wcf做一個可以上傳和下載的功能來管理族庫。
1、用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用於跨機器互動表現的效果較好,所以這裡用這個繫結。對應的環境設定:
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <netTcpBinding> <binding name="MyTcpBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="00:30:00" transferMode="Streamed" > <security mode="None"></security> </binding> </netTcpBinding> </bindings> <services> <service name="ServiceTest.FileService"> <endpoint address="net.tcp://localhost/mysever" binding="netTcpBinding" contract="ServiceTest.IFileService" bindingConfiguration="MyTcpBinding"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:8733/Design_Time_Addresses/ServiceTest/Service1/" /> </baseAddresses> </host> </service> </services> </system.serviceModel>
2.客戶端實現上傳下載
這其中有個重要的一點是,客戶端不能用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<IFileService>.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;
}
}
}
當然還有許多工作要做,比如上傳路徑,限定上傳檔案的字尾名,上傳的族檔案的管理,使用者名稱及密碼的驗證等等,這些細節處理好後,就可以實現族庫管理的功能。