微软的坑,你有踩过吗?

王朝学院·作者佚名  2016-08-28
窄屏简体版  字體: 小  |  中  |  大  |  超大  

最近在做一个很简单的小工具,需求大概是这样的,做一个定时任务系统,定期从服务器上统计相关的业务数据,生成相关报表,然后以Excel方式发送给相关人员。任务很简单,定时任务没问题,生成报表没问题,导出Excel没问题,导出的Excel放在C盘temp目录下,然后设好发送时间,一切都感觉妥妥的,结果也很美好,过了10秒钟(本也测试,时间设得很短),邮件也妥妥的收到,附件中的excel表格也妥妥的能打开,报表也没问题。Oh,yeah,so,easy..,即然结果这么美好,那就打包发布吧。

此处省略100字,就部署完了。

嘀哒。。嘀哒。。,10秒,20秒,30秒,。。。没搞错,为了先跑一个起来,我在正式环境也是设置了10秒运行一次呀?这10秒也太漫长了吧?1分钟了,好吧,应该是出问题了,心里仍在想着是不是哪部署出了问题呀,也不应该呀,就这么简单的一个小工具是吧?

此处省略200字,检查部署没有任何问题。好吧,查日志。

果不其然,报错了,错得还很趾高气扬:

System.FormatException: An invalid character was found in the mail header: '周'.

at System.Net.Mime.MailBnfHelper.GetTokenOrQuotedString(String data, StringBuilder builder)

at System.Net.Mime.ContentDisposition.ToString()

at System.Net.Mime.ContentDisposition.PersistIfNeeded(HeaderCollection headers, Boolean forcePersist)

at System.Net.Mime.MimePart.Send(BaseWriter writer)

at System.Net.Mime.MimeMultipart.Send(BaseWriter writer)

at System.Net.Mail.SmtpClient.Send(MailMessage message)

--- End of inner exception stack trace ---

at System.Net.Mail.SmtpClient.Send(MailMessage message)

没搞错,An invalid character was found in the mail header“周”? 这应该是乱码时,才会这样提示的吧?页面我邮件发送直接是使用SmtpClient,根本就没有设置header呀?

此处省略1000字,各种度娘,各种google,各种恶补邮件头,MIME的知识,各种设置附件ContentType。结果都一样,唯一不一样的就是乱码的字,从“周“变成不是”周“。。

此处省略2000字,突然听同事说有可能和CurrentCulture有关系,顿时眼前一亮,赶紧google一下,果然,有答案了。

.net 4.0中有一个Bug:Culture Bug in ContentDisposition,即只要设置了ContentDisposition的时间,任何时间,如CreationDate,或是ModificationDate,.net内部,会将这些时间通过调用DateTime的toString方法传递给SmtpDateTime,问题就出现在,这些时间格式是和本地语言环境相关的,toString很可能出问题。(官方说法是在vs2013中修复了这个问题)好了,找到问题就好办了,即然和Culture有关,我又不想升级.net Framework,那就让它和CurrentCulture暂时没关系吧。

1varcurrentCulture = Thread.CurrentThread.CurrentCulture;2varattachment =newAttachment(attachmentFile, displayName);3try4{5...6Thread.CurrentThread.CurrentCulture =CultureInfo.InvariantCulture;7attachment.ContentDisposition.CreationDate =File.GetCreationTime(attachmentFilePath);8attachment.ContentDisposition.ModificationDate =File.GetLastWriteTime(attachmentFilePath);9attachment.ContentDisposition.ReadDate =File.GetLastaccessTime(attachmentFilePath);10...11}12finally13{14Thread.CurrentThread.CurrentCulture =currentCulture;15}

果然,那个另人讨厌的”周“不见了,10秒后邮件到了,哈哈,,终于可以收工了。等等。。,为什么我一个好好的Excel附件,发出来后,即没文件名(实际应该有,只是乱码了,没显示出来),里面的内容也是乱码的?天呀,你在和我开玩笑嘛?我本地开发环境都是好好的呀!!

此处省略3000字,各种尝试,各种用网友的办法,各种失去理智的尝试,各种。。无果而终。

就快要放弃的时间,突然想起,有问题找stackoverflow.com呀,度啥娘呀。好吧,我是乱了方寸了。谁让我本应该2小时前就下班的,到现在问题还没头绪呢。果然,这个问题早在n年前就有人发现了,仍然是我们可爱的微软埋下的坑:

[flash=500,400]http://s1.knowsky.com/20160211/1ie1txiaslp06.png[/flash]

[flash=500,400]http://s1.knowsky.com/20160211/bgeny5dmoth06.png[/flash](机器翻译,将就着看哈)。

好吧,我败了。只能怪我爱得太深了,竟不曾怀疑过你。

可我还是不想升级Framework,生产环境,可不是闹着玩的呢。

试着用网友ZYD的方法,把文件名先编码拆分,问题可以得到解决:

[flash=500,400]http://s1.knowsky.com/20160211/5drextuh4ll06.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/fvnjdx1z2sr06.gif[/flash]1...2Attachment attachment =null;3//添加附件4if(!String.IsNullOrEmpty(attachmentFilePath) &&File.Exists(attachmentFilePath))5{6attachment =CreateAttachment(WriteFileToMemory(attachmentFilePath), attachmentFileName,contentType,attachmentFilePath);7message.Attachments.Add(attachment);89}10...1112publicstaticAttachment CreateAttachment(Stream attachmentFile,stringdisplayName,stringcontentType,stringattachmentFilePath)13{14varcurrentCulture = Thread.CurrentThread.CurrentCulture;//.net4.0 bug,15varattachment =newAttachment(attachmentFile, displayName);16try17{18Thread.CurrentThread.CurrentCulture =CultureInfo.InvariantCulture;19attachment.ContentType =newContentType(contentType);20attachment.ContentDisposition.CreationDate =File.GetCreationTime(attachmentFilePath);21attachment.ContentDisposition.ModificationDate =File.GetLastWriteTime(attachmentFilePath);22attachment.ContentDisposition.ReadDate =File.GetLastAccessTime(attachmentFilePath);23attachment.TransferEncoding =TransferEncoding.Base64;24attachment.NameEncoding =Encoding.UTF8;25stringencodedAttachmentName =Convert.ToBase64String(Encoding.UTF8.GetBytes(displayName));26encodedAttachmentName =SplitEncodedAttachmentName(encodedAttachmentName);27attachment.Name =encodedAttachmentName;28}29finally30{31Thread.CurrentThread.CurrentCulture =currentCulture;32}33returnattachment;34}3536PRivatestaticStream WriteFileToMemory(stringfilePath)37{38varfileStream =newFileStream(filePath, FileMode.Open, FileAccess.Read);39returnfileStream;40}4142privatestaticstringSplitEncodedAttachmentName(stringencoded)43{44conststringencodingtoken ="=?UTF-8?B?";45conststringsoftbreak ="?=";46constintmaxChunkLength =30;47intsplitLength = maxChunkLength - encodingtoken.Length - (softbreak.Length *2);48IEnumerable<string> parts =SplitByLength(encoded, splitLength);49stringencodedAttachmentName =encodingtoken;50foreach(varpartinparts)51{52encodedAttachmentName += part + softbreak +encodingtoken;53}54encodedAttachmentName = encodedAttachmentName.Remove(encodedAttachmentName.Length -encodingtoken.Length, encodingtoken.Length);55returnencodedAttachmentName;56}5758privatestaticIEnumerable<string> SplitByLength(stringstringToSplit,intlength)59{60while(stringToSplit.Length >length)61{62yieldreturnstringToSplit.Substring(0, length);63stringToSplit =stringToSplit.Substring(length);64}65if(stringToSplit.Length >0)66{67yieldreturnstringToSplit;68}69}

View Code

过程是坎坷的,结局是美好的!

只能怪我爱得太深了,竟不曾怀疑过你。用它来结语,再好不过了吧!

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航