吐槽net下没有靠谱的FastDFS的sdk之使用thrift实现JAVA和C#互通
事情是这样的,在一个新项目中引入了fastdfs,用这玩意做一些小数据的存储还是很方便的,然后在nuget上就找到了一个FastDFS的sdk,如下图:
一眼就看到了这个top1的sdk,应该会比较靠谱。。。简单的在项目中应用了一下没啥问题就忽悠上线了,然后就悲剧了,测试那边反馈说上传了一个
人群,拉下来的时候少了几个人,我的使用方式是将一批customerid按照bitmap的形式存到byte[]数组传到fastdfs,最后硬着头皮追踪下来发现是这个所谓
的sdk在upload的时候在bytes数组处理上出了bug,这下无语了,哎,nuget上这写sdk的估计也就是个人写着玩玩丢上去的,哪里敢用到生产上,还好在测
试环境发现了,不然又得出什么乱子了。
一:解决办法
问题还得要解决,不过庆幸的是,fastdfs是阿里的一个大牛YuQing写的,那应该有java的sdk更靠谱一点,用maven的话更方便。
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
pull下来以后,这个sdk果然是fastdfs的作者写的,这下子安全感暴增,测试了一下,那个bug用这个sdk果然就没有问题了。。。开心~~~~
然后流程图大概就变成了这个样子。
二:解决C# 和 JAVA的互通问题
互通方式比较多,除了走rest这种面向http的方式,还可以使用thrift,grpc这种tcp的模式,最后我决定还是采用thrift走一遭,目前最新的版本是0.11了。
网址:http://thrift.apache.org/。 看了一下C#的thrift sdk,貌似最高支持0.9.1,网址为:http://archive.apache.org/dist/thrift/0.9.1/ ,
有了这个thrift-0.9.1.exe之后,接下来就可以定义Thrift的DSL,这个DSL可以让thrift-0.9.1.exe 生成各个语言版本的sdk。
1. 定义Thrift DSL
service ThriftService
{
string Upload(: binary data),
binary Download(: string path),
bool Remove(: string path)
}
有人可能会问,这个DSL怎么写,这个大家可以看看官方的DSL的各个关键词描述的网址:http://thrift.apache.org/docs/idl 还是比较简单的,如果不清楚的
话,这个是示例大全: https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob_plain;f=test/ThriftTest.thrift;hb=HEAD ,然后保存为1.thrift。
2. 通过thrift生成 C# SDK
生成的方式可以参考一下官网的模板:
thrift --gen <language> <Thrift filename>
C:\Users\hxc>cd C:\java\lib\thrift C:\java\lib\thrift>thrift-0.9..exe -gen csharp C:\java\lib\thrift\.thrift
可以看到,执行完之后,就多了一个gen-csharp文件夹,点进去看一下,会发现有一个文件名为DSL中定义的ThriftService.cs文件。
3. 通过thrift生成 JAVA SDK
执行完下面这条语句,你会发现你的文件夹又多了一份gen-java 。
C:\java\lib\thrift>thrift-0.9..exe -gen java C:\java\lib\thrift\.thrift
三:SDK集成
改造之后,我们使用JAVA作为服务端,C#作客户端,服务端要做的事情就是通过JAVA来封装FastDFS,然后让C#来调用。
1. JAVA服务端
《1》使用fastDFS 和 Thrift的Maven地址:
<!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.9.</version>
</dependency> <!-- https://mvnrepository.com/artifact/net.oschina.zcx7878/fastdfs-client-java -->
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
《2》 ThriftServiceImpl.java 实现类:
package com.datamip.thrift; import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Date; import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.csource.common.MyException;
import org.csource.fastdfs.StorageClient; import com.fasterxml.jackson.databind.ObjectMapper; /*
* thrift 服务端
*/
public class ThriftServiceImpl implements ThriftService.Iface { public static Logger logger1 = Logger.getLogger(App.class); StorageClient client = null; ObjectMapper objectMapper=new ObjectMapper(); public ThriftServiceImpl() throws IOException, MyException {
client = new FastService().Create();
} //上传文件
public String Upload(ByteBuffer data) { byte[] bytes = data.array(); logger1.info("已成功接受到upload请求: bytes.length="+bytes.length); if(bytes==null || bytes.length==) return ""; // 目前给的 “后缀名为 g1",以后可以动态变更,通过‘阿波罗’动态配置
String[] result = null; try {
result = client.upload_file(bytes, "g1", null); logger1.info("update 上传结果为: "+objectMapper.writeValueAsString(result)); if (result.length < ) return ""; }catch (Exception e) {
logger1.error("upload异常",e);
} return result[];
} // 文件下载
public ByteBuffer Download(String path) throws TException { logger1.info("已成功接受到download请求:"+path); if (path == null || path == "")
return ByteBuffer.allocate(); String[] arr = path.split("\\."); if (arr.length < )
return ByteBuffer.allocate(); String group_name = arr[]; try {
byte[] bytes = client.download_file(group_name, path); logger1.info(String.format("根据path=%s,获取的bytes长度为:%s",path,bytes.length)); return ByteBuffer.wrap(bytes); }catch (Exception e) {
logger1.error("download异常",e);
} // TODO Auto-generated method stub
return ByteBuffer.allocate();
} // 删除文件
public boolean Remove(String path) throws TException { logger1.info("已成功接受到remove请求:"+path); if (path == null || path == "") return false; String[] arr = path.split("\\."); if(arr==null || arr.length<) return false; String group_name = arr[]; try {
int code = client.delete_file(group_name, path); logger1.info(String.format("当前path=%s, groupname=%s,返回状态值=%s",
path,group_name,code)); if(code==) {
return true;
} }catch (Exception e) {
logger1.error("Remove异常",e);
} return false;
}
}
《3》 FastDFS的封装类
package com.datamip.thrift; import java.io.IOException; import org.csource.common.MyException;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer; import com.datamip.utils.PropertiesUtils; public class FastService { public StorageClient Create() throws IOException, MyException { //读取配置文件
String path = PropertiesUtils.getProperties("setting.properties","fastdfs");
return this.Create(path);
} public StorageClient Create(String host) throws IOException, MyException { ClientGlobal.initByTrackers(host); // 3、创建一个TrackerClient对象。
TrackerClient trackerClient = new TrackerClient(); // 4、创建一个TrackerServer对象。
TrackerServer trackerServer = trackerClient.getConnection(); // 5、声明一个StorageServer对象,null。
StorageServer storageServer = null; // 6、获得StorageClient对象。
StorageClient storageClient = new StorageClient(trackerServer, storageServer); return storageClient;
}
}
《4》最后就是AppMain,Thrift开启19999端口。
package com.datamip.thrift; import java.io.IOException; import org.apache.log4j.Logger;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import org.csource.common.MyException; public class App { public static Logger logger1 = Logger.getLogger(App.class); public static void main(String[] args) throws IOException, MyException { try {
TProcessor tprocessor = new ThriftService.Processor<ThriftService.Iface>(new ThriftServiceImpl()); TServerSocket serverTransport = new TServerSocket();
TServer.Args tArgs = new TServer.Args(serverTransport); tArgs.processor(tprocessor);
tArgs.protocolFactory(new TBinaryProtocol.Factory()); logger1.debug("thrift 服务端开启,开放端口 19999"); TServer server = new TSimpleServer(tArgs);
server.serve();
} catch (TTransportException e) {
e.printStackTrace();
}
}
}
2. C#客户端
《1》 从negut上把dll拉下来,然后把生成的ThriftService.cs引入到我们的解决方案中
public partial class ThriftService
{
public interface Iface
{
string Upload(byte[] data);
#if SILVERLIGHT
IAsyncResult Begin_Upload(AsyncCallback callback, object state, byte[] data);
string End_Upload(IAsyncResult asyncResult);
#endif
byte[] Download(string path);
#if SILVERLIGHT
IAsyncResult Begin_Download(AsyncCallback callback, object state, string path);
byte[] End_Download(IAsyncResult asyncResult);
#endif
bool Remove(string path);
#if SILVERLIGHT
IAsyncResult Begin_Remove(AsyncCallback callback, object state, string path);
bool End_Remove(IAsyncResult asyncResult);
#endif
} public class Client : IDisposable, Iface
{
public Client(TProtocol prot) : this(prot, prot)
{
} public Client(TProtocol iprot, TProtocol oprot)
{
iprot_ = iprot;
oprot_ = oprot;
} protected TProtocol iprot_;
protected TProtocol oprot_;
protected int seqid_; public TProtocol InputProtocol
{
get { return iprot_; }
}
public TProtocol OutputProtocol
{
get { return oprot_; }
} #region " IDisposable Support "
private bool _IsDisposed; // IDisposable
public void Dispose()
{
Dispose(true);
} protected virtual void Dispose(bool disposing)
{
if (!_IsDisposed)
{
if (disposing)
{
if (iprot_ != null)
{
((IDisposable)iprot_).Dispose();
}
if (oprot_ != null)
{
((IDisposable)oprot_).Dispose();
}
}
}
_IsDisposed = true;
}
#endregion #if SILVERLIGHT
public IAsyncResult Begin_Upload(AsyncCallback callback, object state, byte[] data)
{
return send_Upload(callback, state, data);
} public string End_Upload(IAsyncResult asyncResult)
{
oprot_.Transport.EndFlush(asyncResult);
return recv_Upload();
} #endif public string Upload(byte[] data)
{
#if !SILVERLIGHT
send_Upload(data);
return recv_Upload(); #else
var asyncResult = Begin_Upload(null, null, data);
return End_Upload(asyncResult); #endif
}
#if SILVERLIGHT
public IAsyncResult send_Upload(AsyncCallback callback, object state, byte[] data)
#else
public void send_Upload(byte[] data)
#endif
{
oprot_.WriteMessageBegin(new TMessage("Upload", TMessageType.Call, seqid_));
Upload_args args = new Upload_args();
args.Data = data;
args.Write(oprot_);
oprot_.WriteMessageEnd();
#if SILVERLIGHT
return oprot_.Transport.BeginFlush(callback, state);
#else
oprot_.Transport.Flush();
#endif
} public string recv_Upload()
{
TMessage msg = iprot_.ReadMessageBegin();
if (msg.Type == TMessageType.Exception)
{
TApplicationException x = TApplicationException.Read(iprot_);
iprot_.ReadMessageEnd();
throw x;
}
Upload_result result = new Upload_result();
result.Read(iprot_);
iprot_.ReadMessageEnd();
if (result.__isset.success)
{
return result.Success;
}
throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "Upload failed: unknown result");
} #if SILVERLIGHT
public IAsyncResult Begin_Download(AsyncCallback callback, object state, string path)
{
return send_Download(callback, state, path);
} public byte[] End_Download(IAsyncResult asyncResult)
{
oprot_.Transport.EndFlush(asyncResult);
return recv_Download();
} #endif public byte[] Download(string path)
{
#if !SILVERLIGHT
send_Download(path);
return recv_Download(); #else
var asyncResult = Begin_Download(null, null, path);
return End_Download(asyncResult); #endif
}
#if SILVERLIGHT
public IAsyncResult send_Download(AsyncCallback callback, object state, string path)
#else
public void send_Download(string path)
#endif
{
oprot_.WriteMessageBegin(new TMessage("Download", TMessageType.Call, seqid_));
Download_args args = new Download_args();
args.Path = path;
args.Write(oprot_);
oprot_.WriteMessageEnd();
#if SILVERLIGHT
return oprot_.Transport.BeginFlush(callback, state);
#else
oprot_.Transport.Flush();
#endif
} public byte[] recv_Download()
{
TMessage msg = iprot_.ReadMessageBegin();
if (msg.Type == TMessageType.Exception)
{
TApplicationException x = TApplicationException.Read(iprot_);
iprot_.ReadMessageEnd();
throw x;
}
Download_result result = new Download_result();
result.Read(iprot_);
iprot_.ReadMessageEnd();
if (result.__isset.success)
{
return result.Success;
}
throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "Download failed: unknown result");
} #if SILVERLIGHT
public IAsyncResult Begin_Remove(AsyncCallback callback, object state, string path)
{
return send_Remove(callback, state, path);
} public bool End_Remove(IAsyncResult asyncResult)
{
oprot_.Transport.EndFlush(asyncResult);
return recv_Remove();
} #endif public bool Remove(string path)
{
#if !SILVERLIGHT
send_Remove(path);
return recv_Remove(); #else
var asyncResult = Begin_Remove(null, null, path);
return End_Remove(asyncResult); #endif
}
#if SILVERLIGHT
public IAsyncResult send_Remove(AsyncCallback callback, object state, string path)
#else
public void send_Remove(string path)
#endif
{
oprot_.WriteMessageBegin(new TMessage("Remove", TMessageType.Call, seqid_));
Remove_args args = new Remove_args();
args.Path = path;
args.Write(oprot_);
oprot_.WriteMessageEnd();
#if SILVERLIGHT
return oprot_.Transport.BeginFlush(callback, state);
#else
oprot_.Transport.Flush();
#endif
} public bool recv_Remove()
{
TMessage msg = iprot_.ReadMessageBegin();
if (msg.Type == TMessageType.Exception)
{
TApplicationException x = TApplicationException.Read(iprot_);
iprot_.ReadMessageEnd();
throw x;
}
Remove_result result = new Remove_result();
result.Read(iprot_);
iprot_.ReadMessageEnd();
if (result.__isset.success)
{
return result.Success;
}
throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "Remove failed: unknown result");
} }
public class Processor : TProcessor
{
public Processor(Iface iface)
{
iface_ = iface;
processMap_["Upload"] = Upload_Process;
processMap_["Download"] = Download_Process;
processMap_["Remove"] = Remove_Process;
} protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);
private Iface iface_;
protected Dictionary<string, ProcessFunction> processMap_ = new Dictionary<string, ProcessFunction>(); public bool Process(TProtocol iprot, TProtocol oprot)
{
try
{
TMessage msg = iprot.ReadMessageBegin();
ProcessFunction fn;
processMap_.TryGetValue(msg.Name, out fn);
if (fn == null)
{
TProtocolUtil.Skip(iprot, TType.Struct);
iprot.ReadMessageEnd();
TApplicationException x = new TApplicationException(TApplicationException.ExceptionType.UnknownMethod, "Invalid method name: '" + msg.Name + "'");
oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));
x.Write(oprot);
oprot.WriteMessageEnd();
oprot.Transport.Flush();
return true;
}
fn(msg.SeqID, iprot, oprot);
}
catch (IOException)
{
return false;
}
return true;
} public void Upload_Process(int seqid, TProtocol iprot, TProtocol oprot)
{
Upload_args args = new Upload_args();
args.Read(iprot);
iprot.ReadMessageEnd();
Upload_result result = new Upload_result();
result.Success = iface_.Upload(args.Data);
oprot.WriteMessageBegin(new TMessage("Upload", TMessageType.Reply, seqid));
result.Write(oprot);
oprot.WriteMessageEnd();
oprot.Transport.Flush();
} public void Download_Process(int seqid, TProtocol iprot, TProtocol oprot)
{
Download_args args = new Download_args();
args.Read(iprot);
iprot.ReadMessageEnd();
Download_result result = new Download_result();
result.Success = iface_.Download(args.Path);
oprot.WriteMessageBegin(new TMessage("Download", TMessageType.Reply, seqid));
result.Write(oprot);
oprot.WriteMessageEnd();
oprot.Transport.Flush();
} public void Remove_Process(int seqid, TProtocol iprot, TProtocol oprot)
{
Remove_args args = new Remove_args();
args.Read(iprot);
iprot.ReadMessageEnd();
Remove_result result = new Remove_result();
result.Success = iface_.Remove(args.Path);
oprot.WriteMessageBegin(new TMessage("Remove", TMessageType.Reply, seqid));
result.Write(oprot);
oprot.WriteMessageEnd();
oprot.Transport.Flush();
} } #if !SILVERLIGHT
[Serializable]
#endif
public partial class Upload_args : TBase
{
private byte[] _data; public byte[] Data
{
get
{
return _data;
}
set
{
__isset.data = true;
this._data = value;
}
} public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset
{
public bool data;
} public Upload_args()
{
} public void Read(TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop)
{
break;
}
switch (field.ID)
{
case :
if (field.Type == TType.String)
{
Data = iprot.ReadBinary();
}
else
{
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
} public void Write(TProtocol oprot)
{
TStruct struc = new TStruct("Upload_args");
oprot.WriteStructBegin(struc);
TField field = new TField();
if (Data != null && __isset.data)
{
field.Name = "data";
field.Type = TType.String;
field.ID = ;
oprot.WriteFieldBegin(field);
oprot.WriteBinary(Data);
oprot.WriteFieldEnd();
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
} public override string ToString()
{
StringBuilder sb = new StringBuilder("Upload_args(");
sb.Append("Data: ");
sb.Append(Data);
sb.Append(")");
return sb.ToString();
} } #if !SILVERLIGHT
[Serializable]
#endif
public partial class Upload_result : TBase
{
private string _success; public string Success
{
get
{
return _success;
}
set
{
__isset.success = true;
this._success = value;
}
} public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset
{
public bool success;
} public Upload_result()
{
} public void Read(TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop)
{
break;
}
switch (field.ID)
{
case :
if (field.Type == TType.String)
{
Success = iprot.ReadString();
}
else
{
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
} public void Write(TProtocol oprot)
{
TStruct struc = new TStruct("Upload_result");
oprot.WriteStructBegin(struc);
TField field = new TField(); if (this.__isset.success)
{
if (Success != null)
{
field.Name = "Success";
field.Type = TType.String;
field.ID = ;
oprot.WriteFieldBegin(field);
oprot.WriteString(Success);
oprot.WriteFieldEnd();
}
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
} public override string ToString()
{
StringBuilder sb = new StringBuilder("Upload_result(");
sb.Append("Success: ");
sb.Append(Success);
sb.Append(")");
return sb.ToString();
} } #if !SILVERLIGHT
[Serializable]
#endif
public partial class Download_args : TBase
{
private string _path; public string Path
{
get
{
return _path;
}
set
{
__isset.path = true;
this._path = value;
}
} public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset
{
public bool path;
} public Download_args()
{
} public void Read(TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop)
{
break;
}
switch (field.ID)
{
case :
if (field.Type == TType.String)
{
Path = iprot.ReadString();
}
else
{
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
} public void Write(TProtocol oprot)
{
TStruct struc = new TStruct("Download_args");
oprot.WriteStructBegin(struc);
TField field = new TField();
if (Path != null && __isset.path)
{
field.Name = "path";
field.Type = TType.String;
field.ID = ;
oprot.WriteFieldBegin(field);
oprot.WriteString(Path);
oprot.WriteFieldEnd();
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
} public override string ToString()
{
StringBuilder sb = new StringBuilder("Download_args(");
sb.Append("Path: ");
sb.Append(Path);
sb.Append(")");
return sb.ToString();
} } #if !SILVERLIGHT
[Serializable]
#endif
public partial class Download_result : TBase
{
private byte[] _success; public byte[] Success
{
get
{
return _success;
}
set
{
__isset.success = true;
this._success = value;
}
} public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset
{
public bool success;
} public Download_result()
{
} public void Read(TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop)
{
break;
}
switch (field.ID)
{
case :
if (field.Type == TType.String)
{
Success = iprot.ReadBinary();
}
else
{
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
} public void Write(TProtocol oprot)
{
TStruct struc = new TStruct("Download_result");
oprot.WriteStructBegin(struc);
TField field = new TField(); if (this.__isset.success)
{
if (Success != null)
{
field.Name = "Success";
field.Type = TType.String;
field.ID = ;
oprot.WriteFieldBegin(field);
oprot.WriteBinary(Success);
oprot.WriteFieldEnd();
}
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
} public override string ToString()
{
StringBuilder sb = new StringBuilder("Download_result(");
sb.Append("Success: ");
sb.Append(Success);
sb.Append(")");
return sb.ToString();
} } #if !SILVERLIGHT
[Serializable]
#endif
public partial class Remove_args : TBase
{
private string _path; public string Path
{
get
{
return _path;
}
set
{
__isset.path = true;
this._path = value;
}
} public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset
{
public bool path;
} public Remove_args()
{
} public void Read(TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop)
{
break;
}
switch (field.ID)
{
case :
if (field.Type == TType.String)
{
Path = iprot.ReadString();
}
else
{
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
} public void Write(TProtocol oprot)
{
TStruct struc = new TStruct("Remove_args");
oprot.WriteStructBegin(struc);
TField field = new TField();
if (Path != null && __isset.path)
{
field.Name = "path";
field.Type = TType.String;
field.ID = ;
oprot.WriteFieldBegin(field);
oprot.WriteString(Path);
oprot.WriteFieldEnd();
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
} public override string ToString()
{
StringBuilder sb = new StringBuilder("Remove_args(");
sb.Append("Path: ");
sb.Append(Path);
sb.Append(")");
return sb.ToString();
} } #if !SILVERLIGHT
[Serializable]
#endif
public partial class Remove_result : TBase
{
private bool _success; public bool Success
{
get
{
return _success;
}
set
{
__isset.success = true;
this._success = value;
}
} public Isset __isset;
#if !SILVERLIGHT
[Serializable]
#endif
public struct Isset
{
public bool success;
} public Remove_result()
{
} public void Read(TProtocol iprot)
{
TField field;
iprot.ReadStructBegin();
while (true)
{
field = iprot.ReadFieldBegin();
if (field.Type == TType.Stop)
{
break;
}
switch (field.ID)
{
case :
if (field.Type == TType.Bool)
{
Success = iprot.ReadBool();
}
else
{
TProtocolUtil.Skip(iprot, field.Type);
}
break;
default:
TProtocolUtil.Skip(iprot, field.Type);
break;
}
iprot.ReadFieldEnd();
}
iprot.ReadStructEnd();
} public void Write(TProtocol oprot)
{
TStruct struc = new TStruct("Remove_result");
oprot.WriteStructBegin(struc);
TField field = new TField(); if (this.__isset.success)
{
field.Name = "Success";
field.Type = TType.Bool;
field.ID = ;
oprot.WriteFieldBegin(field);
oprot.WriteBool(Success);
oprot.WriteFieldEnd();
}
oprot.WriteFieldStop();
oprot.WriteStructEnd();
} public override string ToString()
{
StringBuilder sb = new StringBuilder("Remove_result(");
sb.Append("Success: ");
sb.Append(Success);
sb.Append(")");
return sb.ToString();
} } }
《2》 封装一个简单的CURD操作
public class ThriftSHelper
{
private static string fastdfs = ConfigurationManager.AppSettings["fastdfs"]; TTransport transport = null;
TProtocol protocol = null;
ThriftService.Client client = null; public ThriftSHelper()
{
var arr = fastdfs.Split(':');
var host = arr[];
var port = Convert.ToInt32(arr[]); transport = new TSocket(host, port);
protocol = new TBinaryProtocol(transport);
client = new ThriftService.Client(protocol);
} public static ThriftSHelper Create()
{
return new ThriftSHelper();
} public string UploadFile(BitArray bit)
{
string path = string.Empty; try
{
var bytes = new byte[Convert.ToInt32(Math.Ceiling((double)bit.Length / ))]; transport.Open(); bit.CopyTo(bytes, ); path = client.Upload(bytes);
}
catch (Exception ex)
{
LogHelper.Error(ex);
}
finally
{
transport.Close();
} return path;
} /// <summary>
/// 下载文件
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public BitArray DownloadFile(string fileName)
{
BitArray bitArray = null; try
{
transport.Open(); var bytes = client.Download(fileName); return new BitArray(bytes);
}
catch (Exception ex)
{
LogHelper.WriteLog(fileName, ex);
}
finally
{
transport.Close();
} return bitArray;
} /// <summary>
/// 删除文件
/// </summary>
/// <param name="fileName"></param>
public void RemoveFile(string fileName)
{
try
{
transport.Open(); client.Remove(fileName);
}
catch (Exception ex)
{
LogHelper.WriteLog(ex);
}
finally
{
transport.Close();
}
}
}
好了,这个问题我们就这样完美解决了,跑在生产上还是蛮好的。
吐槽net下没有靠谱的FastDFS的sdk之使用thrift实现JAVA和C#互通的更多相关文章
- 短视频sdk:选择一个靠谱的短视频SDK 你需要了解这些
2017 年,短视频成为了内容创业的新风口,各种短视频 App 如雨后春笋般先后上线.随着互联网内容消费升级,视频越来越像文字.图片一样,成为每一个 App 不可或缺的一部分. 为了能够更好地聚焦于业 ...
- ubuntu下使用golang、qml与ubuntu sdk开发桌面应用
ubuntu下使用golang.qml与ubuntu sdk开发桌面应用 (简单示例) 找了很长时间go的gui库,试了gtk,准备试qt的时候发现了这个qml库,试了下很好用. 准备工作 1.Go ...
- myecplise上将工程部署到应用下时,经常出现 An internal error occurred during: "Add Deployment". java.lang.NullPointEx
myecplise上将工程部署到应用下时,经常出现 An internal error occurred during: "Add Deployment". java.lang.N ...
- Linux下离线安装docker与fastDFS
一.Linux下离线安装Docker 基础环境 1.操作系统:CentOS 7 2.Docker版本:docker-19.03.9.tgz 官方下载地址(打不开可能需要科学-上网) 3.官方参考文档: ...
- windows 下文件上传到fastdfs
php.ini 配置 [fastdfs]; the base pathfastdfs_client.base_path = D:/tmp ; connect timeout in seconds; d ...
- Ubuntu16.04下ZeroC ICE的安装与使用示例(Qt C++ 和 Java)
项目需求:在Ubuntu16.04系统下安装并使用ICEgrid 3.7进行c++和Java Springboot开发环境的通信,下面逐一介绍各个步骤的详解: 一:Ice Lib的安装 参考官网地址: ...
- ubuntu下使用golang、qml与ubuntu sdk开发桌面应用 (简单示例)
找了很长时间go的gui库,试了gtk,准备试qt的时候发现了这个qml库,试了下很好用. ##准备工作 **1.Go 1.2RC1** go的版本应该不能低于这个,我是在1.2RC发布当天升级后发现 ...
- Windows环境下教你用Eclipse ADT 插件生成.h/.so文件,Java下调用JNI,轻松学习JNI
准备工作:Eclipse ADT IDE 开发工具,NDK .Java 环境,博主的配置是:Windows x86 , ADT Build: v22.3.0-887826 , JAVA 1.7, ND ...
- windows8.1下android开发环境搭建(Eclipse+Android sdk+ADT+Genymotion)
一.基本jdk.eclipse环境 二.android sdk 1.下载安装:https://developer.android.com/sdk/installing/index.html?pkg=t ...
随机推荐
- linux yum源配置及vim运用
redhat7默认没有yum模板,需要自己创建[root@localhost ~]# mount /dev/cdrom /root/iso/(挂载镜像)mount: /dev/sr0 写保护,将以只读 ...
- file_get_contents函数不能使用的解决方法
今天开发微信公众平台的时候 使用file_get_contents 去获得token 结果一直返回false.百度了一下,大部分都是说用curl 偶然发现可能是openssl没有开启的问题,开启ope ...
- APACHE服务器出现No input file specified.的完美解决方案
启用REWRITE的伪静态功能的时候,首页可以访问,而访问内页的时候,就提示:“No input file specified.” 原因在于使用的PHP是fast_cgi模式,而在某些情况下,不能正确 ...
- 【mysql】mysql主从复制
mysql主从复制配置 主服务器:192.168.0.100 从服务器 192.168.0.101 主服务器配置 my.ini(window下 linux 下是my.cnf) #开启二进制日志 log ...
- 关于TS流的解析
字节.在TS流里可以填入很多类型的数据,如视频.音频.自定义信息等.他的包的结构为,包头为4个字节,负载为184个字节(这184个字节不一定都是有效数据,有一些可能为填充数据). 工作形式: 因为在T ...
- Caused by:org.hibernate.MappingNotFoundException:resouce:com/you/model/Monkey.hbm.xml not found
1.错误描述 Caused by:org.hibernate.MappingNotFoundException:resouce:com/you/model/Monkey.hbm.xml not fou ...
- HTML5不允许写结束标记的元素
HTML5不允许写结束标记的元素 1.area 2.base 3.br 4.col 5.command 6.embed 7.img 8.hr 9.keygen 10.link 11.meta 12.p ...
- pat1091-1100
1091bfs傻逼题,dfs会爆栈 #include<iostream> #include<cstdio> #include<cstring> #include&l ...
- 权限的分类(shiro项目中来的五)
第一种权限:菜单栏展示还是不展示的权限(粗颗粒) 实现方法,在SYS_ROLE表中添加一个字段rights,通过 public static BigInteger sumRights(String[] ...
- freemarker中的round、floor和ceiling数字的舍入处理(十七)
1.简易说明 (1)round:四舍五入 (2)floor:向下取整 (3)ceiling:向上取整 2.举例说明 <#--freemarker中的round.floor和ceiling数字的舍 ...