protobuf傳文件存入oracle
?
前臺加載一個文件到打包到protobuf中:
public static Intf_R upload_file(int iInsId, int iBizType, int iMenuType, string sFileName, string sRemark)
{
request_p_file_upload.Builder
req = new
request_p_file_upload.Builder();
request_p_file_upload_p1.Builder target = new request_p_file_upload_p1.Builder();
target.InsId = iInsId;
target.OisBizType = iBizType;
target.OisMenuType = iBizType;
target.OisBizType = iMenuType;
target.FileName = sFileName;
target.Remark = sRemark;
byte[] ctrlBuffer = File.ReadAllBytes(sFileName);
int fileSize = ctrlBuffer.Length;
int file0ffset = 0;
target.FileContent = ByteString.CopyFrom(ctrlBuffer, file0ffset, fileSize);
req.AddList1(target);
?
AmqpMessage
in_msg = new
AmqpMessage
IAmqpMessage result = Global.Get<ICOMM>().Send("asf.biz","p_file_upload", in_msg);
response_p_file_upload rsp = response_p_file_upload.ParseFrom(result.Content);
IList<response_p_file_upload_p1> queryList = rsp.List1List;
Intf_R ros = new Intf_R();
foreach (var item in queryList)
{
ros.ID = item.ErrorId;
ros.BizErrorinfo = item.ErrorMsg;
}
return ros;
}
?
關鍵代碼已經加粗,使用protobuf的ByteString加載一段二進制流;
後臺處理代碼:
void write_p_file_upload::execute()
{
????
????request->ParseFromArray(in->getContent(), in->getContentSize());
????LOGWARN("request: " << request->DebugString());
????string user_token = in->getProperty("user_token");
????
????iociconnection* conn = context->get_oracle_connection();
????ocilib::Connection* cn = conn->get_connection();
????ocilib::Statement st(*cn);
????string sql = "insert into tinsfile(ins_op_id,ins_id,ois_biz_type,ois_menu_type,file_name,remark,user_id,op_date,op_time,file_content) "
????????"values (:ins_op_id, :ins_id, :ois_biz_type, :ois_menu_type, :file_name, :remark, :user_id, "
????????"to_number(to_char(SYSDATE,‘YYYYMMDD‘)), to_number(to_char(SYSDATE,‘HH24mmss‘)), :file_content) ";
????st.Prepare(sql);
?
????long long ins_op_id = get_seq_id("seq_ins_op_id", context->get_plugin_context());
????int ins_id = request->list1().Get(0).ins_id();
????int ois_biz_type = request->list1().Get(0).ois_biz_type();
????int ois_menu_type = request->list1().Get(0).ois_menu_type();
????ocilib::ostring file_name = request->list1().Get(0).file_name();
????ocilib::ostring remark = request->list1().Get(0).remark();
????int user_id = 0;
????string user_id_str = in->getProperty("user_id");
????if (user_id_str.empty())
????{
????????user_id = 0;
????}
????else
????{
????????user_id = boost::lexical_cast<long long>(user_id_str);
????}
?
?
????ocilib::Blob file_content(*cn);
????vector<unsigned char> list;
????int sLen = request->list1(0).file_content().length();
????LOGWARN("sLen = " << sLen);
//????list.resize(sLen);//會出現插入00字節的問題
????LOGWARN("list size = " << list.size());????
????for (int i = 0; i < sLen; i++)
????{
????????list.push_back(request->list1(0).file_content().at(i));
????}
????LOGWARN("list date size = " << list.size());
????int iCnt = file_content.Write(list);
????file_content.Seek(ocilib::SeekModeValues::SeekSet, 0);
????LOGWARN("Blob len = " << file_content.GetLength() << ", iCnt = " << iCnt);
????st.Bind<long long>(":ins_op_id", ins_op_id, ocilib::BindInfo::InOut);
????st.Bind<int>(":ins_id", ins_id, ocilib::BindInfo::InOut);
????st.Bind<int>(":ois_biz_type", ois_biz_type, ocilib::BindInfo::InOut);
????st.Bind<int>(":ois_menu_type", ois_menu_type, ocilib::BindInfo::InOut);
????st.Bind<ocilib::ostring,int>(":file_name", file_name, 1024, ocilib::BindInfo::InOut);
????st.Bind<ocilib::ostring, int>(":remark", remark, 1024, ocilib::BindInfo::InOut);
????st.Bind<int>(":user_id", user_id, ocilib::BindInfo::InOut);
????st.Bind<ocilib::Blob>(":file_content", file_content, ocilib::BindInfo::InOut);
????LOGWARN("sql: " << st.GetSql());
????st.ExecutePrepared();
????cn->Commit();
????int iRow = st.GetAffectedRows();
????if (iRow == 0)
????{
????????response_p_file_upload_p1 * out1 = response->add_list1();
????????out1->set_error_id(-1);
????????out1->set_error_msg("上傳附件失敗,請重試");
????}
????else
????{
????????response_p_file_upload_p1 * out1 = response->add_list1();
????????out1->set_error_id(0);
????????out1->set_error_msg("");
????}
????LOGWARN("response: " << response->DebugString());
}
?
加粗部分表示關鍵代碼;
從oracle取出文件打包返回給前臺:
void write_p_file_download::execute()
{
????request->ParseFromArray(in->getContent(), in->getContentSize());
????LOGWARN("request: " << request->DebugString());
????string user_token = in->getProperty("user_token");
?
????iociconnection* conn = context->get_oracle_connection();
????ocilib::Connection* cn = conn->get_connection();
????ocilib::Statement st(*cn);
????string sql = "select file_content from tinsfile where ins_op_id = :ins_op_id ";
????st.Prepare(sql);
?
????int ins_op_id = request->list1().Get(0).ins_op_id();
????
?
????ocilib::Blob file_content(*cn);
????st.Bind<int>(":ins_op_id", ins_op_id, ocilib::BindInfo::InOut);
????st.ExecutePrepared();
????ocilib::Resultset rs = st.GetResultset();
????if (rs.IsNull())
????{
????????response_p_file_download_p1 * out1 = response->add_list1();
????????out1->set_error_id(-1);
????????out1->set_error_msg("未能找到對應附件");
????????out1->set_file_content(" ");
????}
????else
????{
????????while (rs++)
????????{
????????????file_content = rs.Get<ocilib::Blob>("file_content");
????????????LOGWARN("Blob len = " << file_content.GetLength());
????????}
????????ocilib::Raw raw = file_content.Read(file_content.GetLength());
????????LOGWARN("raw size = " << raw.size());
????????string sFileContent;
????????int iPos = 0;
????????for (int i = 0; i < raw.size(); i++)
????????{
????????????if (raw[i] != ‘\0‘)
????????????{
????????????????iPos = i;
????????????????break;
????????????}
????????}
????????for (int i = iPos; i < raw.size(); i++)
????????{
????????????sFileContent.push_back(raw[i]);
????????}
?
????????response_p_file_download_p1 * out1 = response->add_list1();
????????out1->set_error_id(0);
????????out1->set_error_msg("");
????????out1->set_file_content(sFileContent);
????}
????LOGWARN("response: " << response->DebugString());
}
關鍵點是std::string中可以存儲任意字節,這個和char數組是有區別的;
C#前端重新保存成文件的代碼如下:
public static string download_file(int iInsId)
{
request_p_file_download.Builder req = new request_p_file_download.Builder();
request_p_file_download_p1.Builder target = new request_p_file_download_p1.Builder();
target.InsOpId = iInsId;
req.AddList1(target);
AmqpMessage in_msg = new AmqpMessage() { Content = req.Build().ToByteArray() };
IAmqpMessage result = Global.Get<ICOMM>().Send("asf.biz", "p_file_download", in_msg);
response_p_file_download rsp = response_p_file_download.ParseFrom(result.Content);
IList<response_p_file_download_p1> queryList = rsp.List1List;
string path = "";
if (queryList.Count > 0)
{
if (!string.IsNullOrEmpty(queryList[0].FileContent.ToStringUtf8()))
{
path = "./file.tmp";
using (FileStream _fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read, 1048576, FileOptions.None))
{
queryList[0].FileContent.WriteTo(_fs);
}
}
}
return path;
}
?
?
?
?
?
?
?
?
?
protobuf傳文件存入oracle