public override void StartQuery() { string savepath = SaveFolder + @"\" + DateTime.Now.ToString("yyyyMMddHHmmss"); savepath += myForm.cb_OutputType.SelectedItem.ToString(); OutputFile writer = null; if (savepath.EndsWith(".csv")) { writer = new OutputCsv(comResults); } else { writer = new OutputExcel(comResults); } StringBuilder stbr = new StringBuilder(); string paramCom = "Company_Name like comName and Company_Status eq 01"; string paramID = "Business_Accounting_NO eq comID"; int errCount = 0, index = 0; string comName = string.Empty, comID = string.Empty; Console.WriteLine("程式將從本地直接查詢商業司 API..."); ReadFromExcel(); Console.WriteLine("讀取公司列表完成...準備開始查詢 API..."); Console.WriteLine("共有 {0} 條資料待查詢...", comList.Count); while (index < comList.Count) { if (index % 100 == 0 && index > 0) { Console.WriteLine("已連續查詢 100 條,將等待 10 秒繼續..."); Thread.Sleep(10000); } var currentCom = comList[index]; if (!string.IsNullOrEmpty(currentCom.Company_Name)) { comName = currentCom.Company_Name.Trim(); } if (!string.IsNullOrEmpty(currentCom.Business_Accounting_NO)) { comID = currentCom.Business_Accounting_NO.Trim(); } stbr.Clear(); // 這邊分成用公司名稱和統編兩種 // 統編優先 if (!string.IsNullOrEmpty(comID)) { Console.WriteLine("依照公司統編 {0} 進行查詢", comID); stbr.Append("http://").Append("data.gcis.nat.gov.tw") .Append("/od/data/api/5F64D864-61CB-4D0D-8AD9-492047CC1EA6") .Append("?$format=json&$filter=") .Append(paramID.Replace("comID", comID)) .Append("&$skip=0&$top=50"); } else { Console.WriteLine("依照公司名稱 {0} 進行查詢", comName); stbr.Append("http://").Append("data.gcis.nat.gov.tw") .Append("/od/data/api/6BBA2268-1367-4B42-9CCA-BC17499EBE8C") .Append("?$format=json&$filter=") .Append(paramCom.Replace("comName", comName)); } Console.WriteLine("開始查詢第 {0} / {1} 條資料: {2} ", index + 1, comList.Count, comName); HttpWebResponse response = null; try { WebRequest request = WebRequest.Create(stbr.ToString()); response = request.GetResponse() as HttpWebResponse; } catch (WebException e) { Console.WriteLine(e.Message); } if (response != null && response.StatusCode == HttpStatusCode.OK) { try { using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream)) { string resFromAPI = reader.ReadToEnd(); CompanyInfoResult comResult = null; if (!string.IsNullOrEmpty(resFromAPI)) { CompanyInfo[] comInfos = null; try { comInfos = JsonConvert.DeserializeObject <CompanyInfo[]>(resFromAPI); } catch (JsonReaderException e) { Console.WriteLine(resFromAPI); PrintErrMsgToConsole(e); Console.WriteLine("{0} 查詢過程中發生錯誤,程式已中止", comName); Thread.Sleep(3000); writer.Output(savepath); MessageBox.Show("商業司 API 錯誤,部份資料已導出,請洽程式開發人員"); return; } CompanyInfo cInfo = null; bool NameMatch = false; if (comInfos.Length > 1) { cInfo = comInfos.Where(c => c.Company_Name.Equals(comName)).FirstOrDefault(); NameMatch = (cInfo != default(CompanyInfo)); } if (cInfo == null || cInfo == default(CompanyInfo)) { cInfo = comInfos[0]; } comResult = new CompanyInfoResult { Business_Accounting_NO = cInfo.Business_Accounting_NO, Company_Status_Desc = cInfo.Company_Status_Desc, Company_Name = cInfo.Company_Name, Capital_Stock_Amount = cInfo.Capital_Stock_Amount, Paid_In_Capital_Amount = cInfo.Paid_In_Capital_Amount, Responsible_Name = cInfo.Responsible_Name, Company_Location = cInfo.Company_Location, Register_Organization_Desc = cInfo.Register_Organization_Desc, Company_Setup_Date = cInfo.Company_Setup_Date, Change_Of_Approval_Data = cInfo.Change_Of_Approval_Data, Duplicate = (comInfos.Length > 1), NameMatch = NameMatch, ErrNotice = false }; } else { comResult = new CompanyInfoResult { Company_Name = comName, NoData = true }; } //Console.WriteLine(JsonConvert.SerializeObject(comResult)); comResults.Add(comResult); Thread.Sleep(2000); } } Console.WriteLine("查詢 {0} 完成", comName); index++; } catch (IOException e) { PrintErrMsgToConsole(e); errCount++; Console.WriteLine("查詢 {0} 時出現連線錯誤,將等候 10 秒重試...", comName); Thread.Sleep(10000); continue; } catch (JsonSerializationException e) { PrintErrMsgToConsole(e); errCount++; Console.WriteLine("查詢 {0} 時回應資料無法解析,將等候 5 秒 重試...", comName); Thread.Sleep(5000); continue; } catch (Exception e) { Console.WriteLine(e.Message); errCount++; Console.WriteLine("查詢 {0} 時發生不明原因錯誤,將等候 10 秒重試...", comName); Thread.Sleep(10000); continue; } finally { if (errCount >= 3) { index++; errCount = 0; CompanyInfoResult err = new CompanyInfoResult { Company_Name = comName, ErrNotice = true }; //Console.WriteLine(JsonConvert.SerializeObject(err)); comResults.Add(err); Console.WriteLine("查詢 {0} 時發生錯誤已達 3 次,錯誤代碼 {1},將暫時跳過", comName, response.StatusCode.ToString()); } } } else { if (errCount >= 3) { index++; errCount = 0; CompanyInfoResult err = new CompanyInfoResult { Company_Name = comName, ErrNotice = true }; comResults.Add(err); Console.WriteLine("查詢 {0} 時發生錯誤已達 3 次,將暫時跳過...", comName); continue; } errCount++; Console.WriteLine("查詢 {0} 時出現連線錯誤,將等候 10 秒重試...", comName); Thread.Sleep(10000); continue; } } Console.WriteLine("批次查詢作業完畢"); writer.Output(savepath); MessageBox.Show("批次查詢作業完畢!"); }
/* * 當收到 Server 傳來的訊息時 * 1. added 表示已經收到連線請求,並排入等待。 * 2. ready 表示 Server 已經準備好接收查詢列表。 * 3. 收到 result: 開頭的訊息,表示此為 Server 回傳的公司基本資料。 * 4. finish 表示查詢作業已經完成。 * Server 回傳的資料因為是一筆一筆回傳,基本上不會超過 buffer 大小。 * 本來有想過全部查完再一次回傳,但風險太高,途中如果發生錯誤,那 Client 可能經過漫長等待還無法收到回應。 * 一筆一筆傳先儲存在 Client 端,即使 Server 發生錯誤,Client 也能輸出部分資料,下次再從還沒查的地方繼續。 */ private void CommunicateWithServer() { int reclength = 0; NetworkStream netStream = client.GetStream(); byte[] buffer = new byte[1024]; List <CompanyInfoResult> result = new List <CompanyInfoResult>(); string savepath = SaveFolder + @"\" + DateTime.Now.ToString("yyyyMMddHHmmss"); // 這裡要讀取使用者選擇的輸出檔案類型,同樣要委託主執行緒去取得。 savepath += myForm.Invoke(new returnFileType(() => { return(myForm.cb_OutputType.SelectedItem.ToString()); })); OutputFile writer = null; if (savepath.EndsWith(".csv")) { writer = new OutputCsv(result); } else { writer = new OutputExcel(result); } while (client.Connected) { try { if ((reclength = netStream.Read(buffer, 0, buffer.Length)) != 0) { string recMessage = Encoding.UTF8.GetString(buffer, 0, reclength); Console.WriteLine(recMessage); if (recMessage.Equals("finish")) { writer.Output(savepath); result.Clear(); client.Close(); MessageBox.Show("匯出完成!"); } else if (recMessage.Equals("added")) { Console.WriteLine("已連線,等待接受服務..."); } else if (recMessage.Equals("ready")) { Console.WriteLine("開始讀取 Excel 公司列表..."); comList.Clear(); ReadFromExcel(); ComRequest request = new ComRequest { comList = comList.ToArray() }; SendToServer(netStream, JsonConvert.SerializeObject(request)); Console.WriteLine("送出查詢清單..."); client.ReceiveTimeout = TimeOut; } else if (recMessage.Equals("JsonErr")) { Console.WriteLine("商業司 API 回傳錯誤,請洽程式開發人員"); writer.Output(savepath); result.Clear(); client.Close(); MessageBox.Show("商業司 API 錯誤,若有部份資料已導出,請洽程式開發人員"); } else if (recMessage.StartsWith("result:")) { // 公司資料 try { recMessage = recMessage.Replace("result:", string.Empty); var info = JsonConvert.DeserializeObject <CompanyInfoResult>(recMessage); result.Add(info); } catch (Exception e) { PrintErrMsgToConsole(e); } } } } catch (IOException e) { // Server斷線 MessageBox.Show(e.Message); netStream.Close(); client.Close(); } } if (result.Count > 0) { writer.Output(savepath); MessageBox.Show("連線中斷,先導出部分資料"); } }