EWS + Exchange 2007: получение встроенных изображений - PullRequest
2 голосов
/ 11 июля 2011

Работая в C # с EWS Managed API, у нас возникают проблемы с эффективным извлечением изображений, сохраненных в виде встроенных вложений.

Конечная точка заключается в отображении электронного письма со встроенными изображениями в виде полностью сформированной html-страницы напанель.Код, который мы в настоящее время используем:

     string sHTMLCOntent = item.Body;

      FileAttachment[] attachments = null;

      if (item.Attachments.Count != 0)
      {
        attachments = new FileAttachment[item.Attachments.Count];
        for (int i = 0; i < item.Attachments.Count; i++)
        {
          string sType = item.Attachments[i].ContentType.ToLower();
          if (sType.Contains("image"))
          {
            attachments[i] = (FileAttachment)item.Attachments[i];
            string sID = attachments[i].ContentId;
            sType = sType.Replace("image/", "");
            string sFilename = sID + "." + sType;
            string sPathPlusFilename = Directory.GetCurrentDirectory() + "\\" + sFilename;
            attachments[i].Load(sFilename);
            string oldString = "cid:" + sID;
            sHTMLCOntent = sHTMLCOntent.Replace(oldString, sPathPlusFilename);
          }
        }
      }

(источник: http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/ad10283a-ea04-4b15-b20a-40cbd9c95b57)

.. хотя это не очень эффективно и замедляет отзывчивость нашего веб-приложения. Есть ли у кого-нибудьлучшее решение для этой проблемы? Мы используем Exchange 2007 с пакетом обновления 1 (SP1), поэтому свойство IsInline не будет работать только как его Exchange 2010.

1 Ответ

8 голосов
/ 25 ноября 2011

Я строю индекс вашего "cid:" first:

private const string CidPattern = "cid:";

private static HashSet<int> BuildCidIndex(string html)
{
    var index = new HashSet<int>();
    var pos = html.IndexOf(CidPattern, 0);
    while (pos > 0)
    {
        var start = pos + CidPattern.Length;
        index.Add(start);
        pos = html.IndexOf(CidPattern, start);
    }
    return index;
}       

Тогда вам нужна функция замены, которая заменяет cids на основе вашего индекса

private static void AdjustIndex(HashSet<int> index, int oldPos, int byHowMuch)
{
    var oldIndex = new List<int>(index);
    index.Clear();
    foreach (var pos in oldIndex)
    {
        if (pos < oldPos)
            index.Add(pos);
        else
            index.Add(pos + byHowMuch);
    }           
}

private static bool ReplaceCid(HashSet<int> index, ref string html, string cid, string path)
{
    var posToRemove = -1;
    foreach (var pos in index)
    {
        if (pos + cid.Length < html.Length && html.Substring(pos, cid.Length) == cid)
        {
            var sb = new StringBuilder();
            sb.Append(html.Substring(0, pos-CidPattern.Length));
            sb.Append(path);
            sb.Append(html.Substring(pos + cid.Length));
            html = sb.ToString();

            posToRemove = pos;
            break;
        }
    }

    if (posToRemove < 0)
        return false;

    index.Remove(posToRemove);
    AdjustIndex(index, posToRemove, path.Length - (CidPattern.Length + cid.Length));

    return true;
}

так что теперь вы можете проверить свои вложения

FileAttachment[] attachments = null;
var index = BuildCidIndex(sHTMLCOntent);
if (index.Count > 0 && item.Attachments.Count > 0)
{
    var basePath = Directory.GetCurrentDirectory();

    attachments = new FileAttachment[item.Attachments.Count];
    for (var i = 0; i < item.Attachments.Count; ++i)
    {
      var type = item.Attachments[i].ContentType.ToLower();
      if (!type.StartsWith("image/")) continue;                    
      type = type.Replace("image/", "");

      var attachment = (FileAttachment)item.Attachments[i];
      var cid = attachment.ContentId;
      var filename = cid + "." + type;
      var path = Path.Combine(basePath, filename);
      if(ReplaceCid(index, ref sHTMLCOntent, cid, path))
      {
         // only load images when they have been found          
         attachment.Load(path);
         attachments[i] = attachment;
      }
   }
}

Дополнительно к этому: вместо непосредственного вызова attachment.Load и передачи пути к изображению напрямую, вы можете создать ссылку на другой сценарий, где вы передадите cid в качестве параметра, а затем вернетесь к обмену для это изображение; тогда процесс загрузки изображения с биржи не блокирует замену html cid и может привести к более быстрой загрузке страницы, так как html может быстрее отправить в браузер. PS: Код не тестируется, просто чтобы вы поняли!

EDIT

Добавлена ​​недостающая функция AdjustIndex.

РЕДАКТИРОВАТЬ 2

Исправлена ​​небольшая ошибка в AdjustIndex

...