开发者

EWS + Exchange 2007: Retrieve inline images

Working in C# with the EWS Managed 开发者_如何学运维API, we're having trouble efficiently retrieving the images stored as inline attachments.

The endpoint is to show an email with inline images as a fully formed html page in a panel. The code we currently us:

     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);
          }
        }
      }

(sourced: http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/ad10283a-ea04-4b15-b20a-40cbd9c95b57)

.. this is not very efficient though and is slowing down the responsiveness of our web app. Does anyone have a better solution for this problem? We are using Exchange 2007 SP1, so the IsInline property wont work as its Exchange 2010 only.


I build an index of your "cid:"s 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;
}       

Then you need a replace function that replaces the cids based on your index

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;
}

so now, you can check your attachments

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;
      }
   }
}

Additional to that: instead of calling attachment.Load right away, and pass the path to the image directly, you could link to another script, where you pass the cid as a parameter and then check back with the exchange for that image; then the process of loading the image from exchange does not block the html cid replacement and could lead to loading the page faster, since the html can send to the browser sooner. PS: Code is not tested, just so you get the idea!

EDIT

Added the missing AdjustIndex function.

EDIT 2

Fixed small bug in AdjustIndex

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜