StreamWriter(ms, new UTF8Encoding(false))可以达到不输出BOM的需求。
winform 通过webservice向服务器提交图片需要注意的地方
最近一个winform项目中需要通过拍照或者上传本地文件或者截图的方式把产品图片上传到服务器,最后选择了服务器部署webservice的方式来进行。其中遇到了一些问题记录下来。
不多说,直接上服务端代码
[WebMethod(Description = "上传文件")]   public bool UploadFiles(string filename, byte[] content)   {       try       {           int index = filename.LastIndexOf(".");           if (index == 0)           {               return false;           }           else           {               string extended = string.Empty;               if (index + 1 == filename.Length)               {                   return false;               }               else               {                   extended = filename.Substring(index + 1);                   if (extended == "jpeg" || extended == "gif" || extended == "jpg" || extended == "png")                   {                       try                       {                           string Path = System.Web.HttpContext.Current.Server.MapPath("~/ProductImages/");                           if (!Directory.Exists(Path))                            {                                Directory.CreateDirectory(Path);                           }                                                    MemoryStream mymemorystream = new MemoryStream(content, 0, content.Length);                                                 File.WriteAllBytes((Path + filename), content);                           return true;                       }                       catch (Exception ex)                       {                           return false;                       }                   }                   else                   {                       return false;                   }               }           }       }       catch       {           return false;       }   } | 
这其实是一种比较通用的方式,不仅可以用来接收图片文件,也可以是其他文件。当然你也可以做一些文件大小的限制,自己添加一个判断就行。没啥好说的,问题也没有出现。
接下来说说winform这边,下图是图片上传部分


至于如何通过拍照和加载图片或者截图上传到picturebox上大家自己去找吧,网上一大堆。
接下来就是把picture的图片上传到服务器了,首先是添加服务引用,这也很简单就不说了,注意如果一个解决方案中有很多项目,而这个图片上传所在的项目不是主项目,那么需要在主项目的app.config文件中添加一个节点,否则会报找不到什么节点的错误。
<system.serviceModel><bindings><basicHttpBinding><binding name="WebServiceSoap" /></basicHttpBinding></bindings><client>bindingConfiguration="WebServiceSoap" contract="WebService.WebServiceSoap"name="WebServiceSoap" /></client></system.serviceModel> | 
接下来就是上传部分了
if (image != null&isnewimage)          {              MemoryStream ms = new MemoryStream();              image.Save(ms, ImageFormat.Png);              byte[] bytes = new byte[ms.Length];              bytes = ms.GetBuffer();                      WebService.WebServiceSoapClient webservice = new WebService.WebServiceSoapClient();              string filename = cInvCode + ".png";              if (webservice.UploadFiles(filename, bytes))              {                                }              else              {                  issaveok = false;                  failreason = "图片上传失败!";                                     return;              }                       } | 
这里首先获取图片资源放到一个image对象中,然后转换为字节数组通过webservice上传,这里我让图片全部以png格式上传,当然你可以以其他格式上传。
刚开始在向字节数组赋值的时候我用的不是bytes = ms.GetBuffer();而是用的ms.Write(bytes, 0, (int)ms.Length);结果文件是可以上传到服务器,但是服务器端的图片文件始终打不开,说可能文件已经损坏,查了半天查不出来原因,最后发现其实还有bytes = ms.GetBuffer();这种方法,一试,问题果然解决,服务器端的图片成为可以预览查看的正常图片了。
好了,这是第一次写博客,写的不好,还请吐槽啊。
Stream.Write 与 StreamWriter.Write 是我们在向流中写数据时,最常用的方法。下面就详细讲解这两个方法。
一、测试方法是否结果相同
首先看下面两段代码左侧是StreamWriter.Write 右侧是Stream.Write:
| 
 1 
2 
3 
4 
5 
6 
 | 
Stream ms = new MemoryStream();string str = "这是测试字符串";StreamWriter sw = new StreamWriter(ms, Encoding.UTF8);sw.Write(str);sw.Flush(); | 
| 
 1 
2 
3 
4 
5 
6 
 | 
Stream ms = new MemoryStream();string str = "这是测试字符串";byte[] buffer = Encoding.UTF8.GetBytes(str);            ms.Write(buffer, 0, buffer.Length);ms.Flush(); | 
上面我们可以看到StreamWriter.Write的可读性更好一些。
但是这两段代码执行后的ms是否是相同的结果呢?
首先我们来看下长度吧,在代码最后分别加上
| 
 1 
2 
 | 
Console.WriteLine("StreamWriter.Write:{0}", ms.Length);Console.WriteLine("Stream.Write:{0}", ms.Length); | 
执行后结果如下:

各位看官,看到这里有何想法?
二、深究原因
下面继续深究一下这个多出来的3个字节
在方法后面都加上如下一段代码将MemoryStream的内容以十六进制的形式打印出来
| 
 1 
2 
3 
4 
5 
6 
7 
8 
 | 
ms.Position = 0;byte[] bytes = new byte[ms.Length];ms.Read(bytes, 0, bytes.Length);foreach (var item in bytes){    Console.Write(item.ToString("X2") + " ");}Console.WriteLine(String.Empty); | 
再次执行结果如下:

这里我们发现用StreamWriter.Write输出多出了EF BB BF这3个字节
Google一下:多出来的这个玩意是 字节顺序记号(英语:byte-order mark,BOM)
在维基百科中可以查到:
| 编码 | 表示 (十六进制) | 表示 (十进制) | 
|---|---|---|
| UTF-8 | EF BB BF | 
239 187 191 | 
| UTF-16(大端序) | FE FF | 
254 255 | 
| UTF-16(小端序) | FF FE | 
255 254 | 
| UTF-32(大端序) | 00 00 FE FF | 
0 0 254 255 | 
| UTF-32(小端序) | FF FE 00 00 | 
255 254 0 0 | 
| UTF-7 | 2B 2F 76和以下的一个字节:[ 38 | 39 | 2B | 2F ] | 
43 47 118和以下的一个字节:[ 56 | 57 | 43 | 47 ] | 
| en:UTF-1 | F7 64 4C | 
247 100 76 | 
| en:UTF-EBCDIC | DD 73 66 73 | 
221 115 102 115 | 
| en:Standard Compression Scheme for Unicode | 0E FE FF | 
14 254 255 | 
| en:BOCU-1 | FB EE 28 及可能跟随着FF | 
251 238 40 及可能跟随着255 | 
ok,了解了这个东西后我们就就需要知道在StreamWriter.Write中能否用代码控制不输出这个BOM吗?
三、查找解决办法
开始反编译StreamWriter.Write这个方法:

大致猜测是红色方框的代码输出了BOM信息,ok再进去看:

果然在这里,看上图红框处,GetPreamble方法是获取编码的字节序列,和我们之前查到的信息完全一致。
好下面继续找这个haveWrittenPreamble有没设置的可能,在Init方法中找到了它的身影。

杯具了,CanSeed没有set方法,Write之前的Position肯定为0,至此结束。
四、结论
由上面的结论,我们可以确定:
1.如果双方协议无BOM时,可以使用Stream.Write方法来输出,或者使用StreamWriter.Write时加入new UTF8Encoding(false)参数。
2.有BOM时,我们可以通过GetPreamble和Stream.Write来完成StreamWriter.Write的功能。
参考文献:
谢谢FJ. Zhou提示
使用StreamWriter sw = new StreamWriter(ms, new UTF8Encoding(false));可以达到不输出BOM的需求。
谢谢dudu提示,已更正。
StreamWriter(ms, new UTF8Encoding(false))可以达到不输出BOM的需求。的更多相关文章
- Encoding.UTF8 与 new UTF8Encoding(false) 有什么区别?
		
System.Text.Encoding.UTF8 是一个静态实例,它省略了 BOM,而 new UTF8Encoding(false) 创建的实例是含有 BOM 的. BOM,即 Byte Orde ...
 - StreamWriter结合UTF-8编码使用不当,会造成BOM(Byte Order Mark )问题生成乱码(转载)
		
问: I was using HttpWebRequest to try a rest api in ASP.NET Core MVC.Here is my HttpWebRequest client ...
 - 无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(二)
		
上一篇文章 "无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(一)"中,我们实现了监视每个页面的执行情况和调用WebService的简单信息. ...
 - .NET Core/.NET之Stream简介
		
之前写了一篇C#装饰模式的文章提到了.NET Core的Stream, 所以这里尽量把Stream介绍全点. (都是书上的内容) .NET Core/.NET的Streams 首先需要知道, Syst ...
 - 9102年了,汇总下HttpClient问题,封印一个
		
如果找的是core的HttpClientFactory 出门右转. 官方写法,高并发下,TCP连接不能快速释放,导致端口占完,无法连接 Dispose 不是马上关闭tcp连接 主动关闭的一方为什么不能 ...
 - .NET Core/.NET之Stream简介    Rx.NET 简介
		
.NET Core/.NET之Stream简介 之前写了一篇C#装饰模式的文章提到了.NET Core的Stream, 所以这里尽量把Stream介绍全点. (都是书上的内容) .NET Core ...
 - 【C#公共帮助类】 Utils 10年代码,最全的系统帮助类
		
为大家分享一下个人的一个Utils系统帮助类,可能有些现在有新的技术替代,自行修改哈~ 这个帮助类主要包含:对象转换处理 .分割字符串.截取字符串.删除最后结尾的一个逗号. 删除最后结尾的指定字符后的 ...
 - 【C#公共帮助类】 Utils最全的系统帮助类
		
最近闲的没事做,自己想着做一些东西,不知不觉居然在博客园找到了这么多公共类,感觉还是挺有用的,平时自己还是用到了好多,就是缺少整理,现在为大家分享一下一个Utils系统帮助类,可能有些现在有新的技术替 ...
 - 完整的系统帮助类Utils
		
//来源:http://www.cnblogs.com/yuangang/p/5477324.html using System; using System.Collections.Generic; ...
 
随机推荐
- 【源代码】StringBuilder和StringBuffer震源深度分析
			
//------------------------------------------------------------------------ 写篇博客不easy.请尊重作者劳动成果. 转载请注 ...
 - 开源 java CMS - FreeCMS2.3员
			
原文地址:http://javaz.cn/site/javaz/site_study/info/2015/28375.html 项目地址:http://www.freeteam.cn/ 会员注冊 打 ...
 - 实战parse_ini_file()及扩展函数解析ini文件完整版
			
文章来源:PHP开发学习门户 地址:http://www.phpthinking.com/archives/587 在PHP站点开发的过程中,往往会用到读取ini參数配置文件,比方须要訪问一些复杂的借 ...
 - C# Parse和Convert的区别分析(转)
			
大家都知道在进行类型转换的时候有连个方法供我们使用就是Convert.to和*.Parse,但是疑问就是什么时候用C 什么时候用P 通俗的解释大家都知道: Convert 用来转换继承自object类 ...
 - NHibernate构建一个ASP.NET MVC应用程序
			
NHibernate构建一个ASP.NET MVC应用程序 什么是Nhibernate? NHibernate是一个面向.NET环境的对象/关系数据库映射工具.对象/关系数据库映射(object/re ...
 - Largest Rectangular Area in a Histogram
			
题目地址:https://oj.leetcode.com/problems/largest-rectangle-in-histogram/ ,刚開始事实上没做这个题,而是在做https://oj.le ...
 - python算法题
			
python几道简单的算法题 最近看了python的语法,但是总感觉不知道怎么使用它,还是先来敲敲一些简单的程序吧. 1.题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都 ...
 - 转载+自练(莫喷)怎样在cocos2d 2.1.4里面使用动画和Texture Packer
			
本文实践自 Ray Wenderlich.Tony Dahbura 的文章<How to Use Animations and Sprite Sheets in Cocos2D 2.X>, ...
 - Appium根据xpath获取控件实例随笔
			
如文章<Appium基于安卓的各种FindElement的控件定位方法实践>所述,Appium拥有众多获取控件的方法.其中一种就是根据控件所在页面的XPATH来定位控件. 本文就是尝试通过 ...
 - 来选择一款适合你网站的CMS建站程序吧
			
1:首页我们要搞清楚什么叫cms? ContentManagementSystem就是cms的全名,意思就是内容管理系统.cms整站系统是以文章系统为核心,增加用户需要的模块,如文章.图片.下载等,提 ...