2015-11-24 38 views
1

我在StackO的幫助下寫了這個方法,但是我一直無法找到一個改進的地方。從收件箱下載附件時,如何減少EWS呼叫?

現在,我遍歷Office 365收件箱中的每條消息,遍歷其附件集合,並將每個文件保存到磁盤(如果它是Excel工作簿)。目前這項工作正在進行中,但會導致大量的Exchange調用。收件箱的大小可能變得非常大,因此需要很長時間才能運行,每次通話時間大約爲0.5秒。

如果我已經計算正確,則調用的數量標度爲(n/100)+ 2n。

  • n是消息的收件箱中的數量(每個消息2個呼叫)
  • 100是pageSize的,因爲我還沒有看到任何比這大(一個呼叫的每一頁)

注意:通常(99.9999%)每條消息只有一個附件,但爲CYA目的添加了內部循環。可能會造成一些內存開銷,但很少或者沒有縮放因子。

我想知道是否有更好的方法,用更少的Web服務調用。是否有EWS方法可以下載批量附件?我對EWS很新,所以我確信我在這裏缺乏理解。 我想要做的是減少pageSizeLoad(path)一批文件到磁盤,減少規模。

爲下面的代碼改進任何建議,相對於減少EWS來電,將不勝感激。

public void SaveAttachmentsFromInbox(string[] extensionFilter = null) 
    { 

     // Default to excel files 
     extensionFilter = extensionFilter ?? new[] { ".xls", ".xlsx" }; 

     // Config for traversing inbox 
     int offset = 0; 
     int pageSize = 100; 
     ItemView view = new ItemView(pageSize, offset, OffsetBasePoint.Beginning); 
     view.PropertySet = PropertySet.FirstClassProperties; 
     FindItemsResults<Item> findResults; 

     // Loop through the inbox 
     // and save all attachments of the designated file types 
     bool more = true; 
     var fileCount = 0; 
     while (more) 
     { 

      findResults = service.FindItems(WellKnownFolderName.Inbox, view); 
      // Load each sheet's data into an Object 
      foreach (var item in findResults.Items) 
      { 
       //get FirstClassProperties 
       item.Load(view.PropertySet); 

       string vendor = GetVendor(EmailMessage.Bind(service, item.Id)); 
       messageIds.Add(item.Id.ToString()); 

       // Save files to disk 
       foreach (FileAttachment file in item.Attachments) 
       { 
        string fileExtension = file.Name.Substring(file.Name.IndexOf('.'), file.Name.Length - file.Name.IndexOf('.')); 

        if (extensionFilter.Contains(fileExtension)) 
        { 
         var fullPath = Path.Combine(path, file.Name); 
         attachmentInfo.Add(fullPath, vendor); 

         // Loads attachment and saves to disk 
         file.Load(fullPath); 

         fileCount++; 
         Console.Write("\rFiles received... {0} ", fileCount); 
        } 
       } 
      } 



      Console.WriteLine(); // Next line 

      more = findResults.MoreAvailable; 
      // Page through inbox if more messages remain 
      if (more) 
      { 
       view.Offset += pageSize; 
      } 
     } 
     Console.WriteLine(attachmentInfo.Count + " Excel Attachment Downloads successful.\n"); 
    } 

回答

2

除了使用AQS來減少從服務器返回的記錄集,您應該使用batchs命令首先使用LoadPropertiesForItems獲取Item屬性(替換您的代碼中的每個項目的綁定),然後您可以批量使用GetAttachments(你需要確保你使用EWS託管API 2.2版本),這將意味着,例如一批100項你做一個FindItems呼叫,一個批次的GetItem調用和批量GetAttachment呼叫寧的附件下載1 * 100 * 100如果您使用綁定和加載。例如類似

  ItemView ivItemView = new ItemView(100); 
     PropertySet flLevel = new PropertySet(BasePropertySet.IdOnly); 
     ivItemView.PropertySet = flLevel; 
     FindItemsResults<Item> faItems = service.FindItems(WellKnownFolderName.Inbox, "attachment:.xlsx OR attatchment:xls", ivItemView); 
     PropertySet slLevel = new PropertySet(BasePropertySet.FirstClassProperties); 
     if (faItems.Items.Count > 0) 
     { 
      service.LoadPropertiesForItems(faItems, slLevel); 
     } 
     List<Attachment> atAttachments = new List<Attachment>(); 
     foreach (Item itItem in faItems.Items) 
     { 
      foreach (Attachment atAttachment in itItem.Attachments) 
      { 
       if (atAttachment is FileAttachment) 
       { 
        string fileExtension = atAttachment.Name.Substring(atAttachment.Name.IndexOf('.'), atAttachment.Name.Length - atAttachment.Name.IndexOf('.')); 
        if (extensionFilter.Contains(fileExtension)) 
        { 
         atAttachments.Add(atAttachment); 

        } 
       } 
      } 
     } 
     service.GetAttachments(atAttachments.ToArray(), BodyType.HTML,null); 
     foreach (FileAttachment FileAttach in atAttachments) 
     { 
      Console.Write(FileAttach.Name); 
      System.IO.File.WriteAllBytes("c:\\export\\" + FileAttach.Name, FileAttach.Content); 
      //save off 
     } 
+0

這就是我一直在尋找的東西。謝謝! – CaptainMarvel

1

如果你的目標的Exchange 2010或更高版本,你可以使用一個FindItem with Advanced Query Syntax

ItemView view = new ItemView(100); 
FindItemsResults<Item> results = service.FindItems(folder, "Has attachment:true", view); 

foreach (Item item in results.Items) 
{ 
    if (item is EmailMessage) 
    { 
     // Get the item and FileAttachments in the same way. 
    } 
} 

我沒有嘗試這樣做我自己,但它是可能的,你可以得到一個更好的使用結果AQS Has attachment:true AND .xlsx

+0

我喜歡這個。不知道AQS。 附件是否可用,而無需再次「加載()」每個單獨的電子郵件項目?這看起來與我現在正在做的事情類似,在一天結束時:將Load()消息加載到內存,然後將附件加載到磁盤。 – CaptainMarvel

+1

我不記得我害怕。不過,我相當肯定你仍然必須像你在代碼中那樣「獲得」每一個結果。 – Tholle

+1

好的,謝謝。我會試驗這個。 – CaptainMarvel