从收件箱下载附件时如何减少 EWS 调用?
How can I reduce EWS calls when downloading attachments from an Inbox?
我在 StackO
的帮助下编写了这个方法,但我一直找不到改进方法。
现在,我遍历 Office 365 收件箱中的每封邮件,遍历其附件集合,并将每个文件保存到磁盘(如果它是 Excel 工作簿)。这目前有效,但会导致大量调用 Exchange。收件箱的大小可能会变得非常大,因此需要很长时间才能 运行,每次通话的时间约为 0.5 秒。
如果我没记错的话,调用次数为 (n / 100) + 2n。
- n 是收件箱中的消息数(每条消息调用 2 次)
- 100 是 pageSize,因为我还没有看到比这更大的东西(每页调用一次)
注意:通常 (99.9999%) 每封邮件只有一个附件,但我为 CYA 添加了内部循环。可能有一些内存开销,但几乎没有比例因子。
我想知道是否有更好的方式来减少 Web 服务调用。有没有可以批量下载附件的EWS方法?我对 EWS 很陌生,所以我确定我在这里缺乏理解。 我要做的是将pageSize
和Load(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");
}
如果您的目标是 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
。
除了使用 AQS 减少从服务器返回的记录集之外,您还应该使用批处理命令首先使用 LoadPropertiesForItems(替换每个项目代码中的绑定)获取项目属性,然后您可以使用 GetAttachments 批量下载附件(您需要确保您使用的是 EWS Managed API 的 2.2 版),这意味着例如您要进行一次 FindItems 调用、一次批量 GetItem 调用和一个 100 件的批次Batch GetAttachment Call 而不是 1 * 100 * 100 如果您使用 Bind 和 Load。例如
ItemView ivItemView = new ItemView(100);
PropertySet flLevel = new PropertySet(BasePropertySet.IdOnly);
ivItemView.PropertySet = flLevel;
FindItemsResults<Item> faItems = service.FindItems(WellKnownFolderName.Inbox, "attachment:.xlsx OR attachment: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
}
我在 StackO
的帮助下编写了这个方法,但我一直找不到改进方法。
现在,我遍历 Office 365 收件箱中的每封邮件,遍历其附件集合,并将每个文件保存到磁盘(如果它是 Excel 工作簿)。这目前有效,但会导致大量调用 Exchange。收件箱的大小可能会变得非常大,因此需要很长时间才能 运行,每次通话的时间约为 0.5 秒。
如果我没记错的话,调用次数为 (n / 100) + 2n。
- n 是收件箱中的消息数(每条消息调用 2 次)
- 100 是 pageSize,因为我还没有看到比这更大的东西(每页调用一次)
注意:通常 (99.9999%) 每封邮件只有一个附件,但我为 CYA 添加了内部循环。可能有一些内存开销,但几乎没有比例因子。
我想知道是否有更好的方式来减少 Web 服务调用。有没有可以批量下载附件的EWS方法?我对 EWS 很陌生,所以我确定我在这里缺乏理解。 我要做的是将pageSize
和Load(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");
}
如果您的目标是 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
。
除了使用 AQS 减少从服务器返回的记录集之外,您还应该使用批处理命令首先使用 LoadPropertiesForItems(替换每个项目代码中的绑定)获取项目属性,然后您可以使用 GetAttachments 批量下载附件(您需要确保您使用的是 EWS Managed API 的 2.2 版),这意味着例如您要进行一次 FindItems 调用、一次批量 GetItem 调用和一个 100 件的批次Batch GetAttachment Call 而不是 1 * 100 * 100 如果您使用 Bind 和 Load。例如
ItemView ivItemView = new ItemView(100);
PropertySet flLevel = new PropertySet(BasePropertySet.IdOnly);
ivItemView.PropertySet = flLevel;
FindItemsResults<Item> faItems = service.FindItems(WellKnownFolderName.Inbox, "attachment:.xlsx OR attachment: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
}