用C#保存IOS发送的图片


在项目中遇到了这么一个问题。移动端上传的图片,在我asp.NET后边接收,但却转换不成图片保存。于是我把接收到的二进制流转换成字符串的形式显示出来。结果大吃一惊。iOS传过来的二进制流不是纯图片的,还有一些图片的格式,名称等。

显示如下:

<span style="font-size:18px;">--Boundary+6638A777949A1B1A  
Content-Disposition: form-data; name="file"; filename="20160523171643.png"  
Content-Type: image/png  
  
�PNG   
IHDR  <  m   �Su   sRGB ���   iDOT         7   (  7  6 T�gf��  @ IDATxd�ٖ7�e��VW�RJMg2�1�HRY��s{�s`7B�X��`f ����7�����������÷��#���on>�(;���:|ה|�{i=ʮi�������������悲K�PF�����=u�m�ȿ9z������[�}��=������N���k��҇8x���H�S��w�K��x��]p��1��z�9x��͡�m�as{��d��-L�n�閶w�'yH��H��G_w��h�|������  
]�[�J�}ݜp=������hO��,��:5�#y�58ݓ���t�v������<>���#��wo���w�    ���}�.��8x����';/7G^lw���ޜ�>|�9�}�9��js��j��e�  
��o7gܟ}"}|�9���6_>��|���.:��\��\�W&ei: }��N�'�W�  
Zկ�ӽ�S~$O(�7�w����tO�|���zwg{�[xt�{ye|R�n��/����I�!�C���  
�����A�\y�;��pl��Ci{lߟ��z@�<span style="color:#FF0000;"><strong>(这里的乱码,是图片的数据部分)</strong></span>  
--Boundary+6638A777949A1B1A--  
</span>  

问题及解决方案

        那么问题来了,怎么分开处理呢?通过各种查询、实验。终于解决了这个问题,基本思路是用正则表达式来匹配里面的键值,如conten-type,filename,匹配完后中间的部分都是图片流数据,就可以直接转换成图片保存起来了。

<span style="font-size:18px;">using System;  
using System.Collections.Generic;  
using System.IO;  
using System.Text;  
using System.Text.RegularExpressions;  
  
namespace Model  
{  
    public class MultipartParser  
    {  
        private byte[] requestData;  
        public MultipartParser(Stream stream)  
        {  
            this.Parse(stream, Encoding.UTF8);  
         //   ParseParameter(stream, Encoding.UTF8);  
        }  
  
        public MultipartParser(Stream stream, Encoding encoding)  
        {  
            this.Parse(stream, encoding);  
        }  
  
        private void Parse(Stream stream, Encoding encoding)  
        {  
            this.Success = false;  
  
            // Read the stream into a byte array  
            byte[] data = ToByteArray(stream);  
            requestData = data;  
  
            // Copy to a string for header parsing  
            string content = encoding.GetString(data);  
  
            // The first line should contain the delimiter  
            int delimiterEndIndex = content.IndexOf("\r\n");  
  
            if (delimiterEndIndex > -1)  
            {  
                string delimiter = content.Substring(0, content.IndexOf("\r\n"));  
  
                // Look for Content-Type  
                Regex re = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");  
                Match contentTypeMatch = re.Match(content);  
  
                // Look for filename  
                re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");  
                Match filenameMatch = re.Match(content);  
  
                // Did we find the required values?  
                if (contentTypeMatch.Success && filenameMatch.Success)  
                {  
                    // Set properties  
                    this.ContentType = contentTypeMatch.Value.Trim();  
                    this.Filename = filenameMatch.Value.Trim();  
  
                    // Get the start & end indexes of the file contents  
                    int startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;  
  
                    byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);  
                    int endIndex = IndexOf(data, delimiterBytes, startIndex);  
  
                    int contentLength = endIndex - startIndex;  
  
                    // Extract the file contents from the byte array  
                    byte[] fileData = new byte[contentLength];  
  
                    Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);  
  
                    this.FileContents = fileData;  
                    this.Success = true;  
                }  
            }  
        }  
  
        private void ParseParameter(Stream stream, Encoding encoding)  
        {  
            this.Success = false;  
  
            // Read the stream into a byte array  
            byte[] data;  
            if (requestData.Length == 0)  
            {  
                data = ToByteArray(stream);  
            }  
            else { data = requestData; }  
            // Copy to a string for header parsing  
            string content = encoding.GetString(data);  
  
            // The first line should contain the delimiter  
            int delimiterEndIndex = content.IndexOf("\r\n");  
  
            if (delimiterEndIndex > -1)  
            {  
                string delimiter = content.Substring(0, content.IndexOf("\r\n"));  
                string[] splitContents = content.Split(new[] {delimiter}, StringSplitOptions.RemoveEmptyEntries);  
                foreach (string t in splitContents)  
                {  
                    // Look for Content-Type  
                    Regex contentTypeRegex = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");  
                    Match contentTypeMatch = contentTypeRegex.Match(t);  
  
                    // Look for name of parameter  
                    Regex re = new Regex(@"(?<=name\=\"")(.*)");  
                    Match name = re.Match(t);  
  
                    // Look for filename  
                    re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");  
                    Match filenameMatch = re.Match(t);  
  
                    // Did we find the required values?  
                    if (name.Success || filenameMatch.Success)  
                    {  
                        // Set properties  
                        //this.ContentType = name.Value.Trim();  
                        int startIndex;  
                        if (filenameMatch.Success)  
                        {  
                            this.Filename = filenameMatch.Value.Trim();  
                        }  
                        if(contentTypeMatch.Success)  
                        {  
                            // Get the start & end indexes of the file contents  
                            startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;  
                        }  
                        else  
                        {  
                            startIndex = name.Index + name.Length + "\r\n\r\n".Length;  
                        }  
  
                        //byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);  
                        //int endIndex = IndexOf(data, delimiterBytes, startIndex);  
  
                        //int contentLength = t.Length - startIndex;  
                        string propertyData = t.Substring(startIndex - 1, t.Length - startIndex);  
                        // Extract the file contents from the byte array  
                        //byte[] paramData = new byte[contentLength];  
  
                        //Buffer.BlockCopy(data, startIndex, paramData, 0, contentLength);  
  
                        MyContent myContent = new MyContent();  
                        myContent.Data = encoding.GetBytes(propertyData);  
                        myContent.StringData = propertyData;  
                        myContent.PropertyName = name.Value.Trim();  
  
                        if (MyContents == null)  
                            MyContents = new List<MyContent>();  
  
                        MyContents.Add(myContent);  
                        this.Success = true;  
                    }  
                }  
            }  
        }  
  
        private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex)  
        {  
            int index = 0;  
            int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);  
  
            if (startPos != -1)  
            {  
                while ((startPos + index) < searchWithin.Length)  
                {  
                    if (searchWithin[startPos + index] == serachFor[index])  
                    {  
                        index++;  
                        if (index == serachFor.Length)  
                        {  
                            return startPos;  
                        }  
                    }  
                    else  
                    {  
                        startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index);  
                        if (startPos == -1)  
                        {  
                            return -1;  
                        }  
                        index = 0;  
                    }  
                }  
            }  
  
            return -1;  
        }  
  
        private byte[] ToByteArray(Stream stream)  
        {  
            byte[] buffer = new byte[32768];  
            using (MemoryStream ms = new MemoryStream())  
            {  
                while (true)  
                {  
                    int read = stream.Read(buffer, 0, buffer.Length);  
                    if (read <= 0)  
                        return ms.ToArray();  
                    ms.Write(buffer, 0, read);  
                }  
            }  
        }  
  
        public List<MyContent> MyContents { get; set; }  
  
        public bool Success  
        {  
            get;  
            private set;  
        }  
  
        public string ContentType  
        {  
            get;  
            private set;  
        }  
  
        public string Filename  
        {  
            get;  
            private set;  
        }  
  
        public byte[] FileContents  
        {  
            get;  
            private set;  
        }  
    }  
  
    public class MyContent  
    {  
        public byte[] Data { get; set; }  
        public string PropertyName { get; set; }  
        public string StringData { get; set; }  
    }  
  
}   </span>  

asp.net后台代码

<span style="font-size:18px;">using System;  
using System.Collections.Generic;  
using System.IO;  
using System.Linq;  
using System.Web;  
using System.Web.UI;  
using System.Web.UI.WebControls;  
  
namespace ITSMToJson  
{  
    public partial class updateFile: System.Web.UI.Page  
    {  
        protected void Page_Load(object sender, EventArgs e)  
        {  
            //假数据  
            //FileStream photo = new FileStream("d://test.jpg", FileMode.Open);  
            //byte[] buffer = new byte[photo.Length];  
            //photo.Read(buffer, 0, buffer.Length);  
  
  
            //获得IOS传过来的二进制流  
            Stream sourceStream = Request.InputStream;  
  
            MultipartParser model = new MultipartParser(sourceStream);//实例化MultipartParse  
            string Filename = model.Filename;      //获得图片名称  
            byte[] FileContents = model.FileContents;     //获得图片流数据  
  
            //获得Web服务上File虚拟路径相对应的物理文件路径  
            string Path = HttpContext.Current.Server.MapPath("/File") + "//" + DateTime.Now.ToString("yyyyMMdd");   
  
            //查看路径是否存在,如果不存在,则创建路径  
            if (!Directory.Exists(Path))  
            {  
                DirectoryInfo foler = Directory.CreateDirectory(Path);  
            }  
  
            //得到要目的文件路径  
            string  filenameaddress = Path+"//"+Filename;  
  
            //将图片流显示成图片并保存起来  
            FileStream targetStream = new FileStream(filenameaddress, FileMode.Create);  
            targetStream.Write(FileContents, 0, FileContents.Length);  
            System.Drawing.Image img = System.Drawing.Image.FromStream(targetStream);  
            targetStream.Close();  
            sourceStream.Close();  
  
        }  
    }  
}

测试用PostMan

小结

        在此还要感谢提供思路和代码的网友。代码就是不断地积累,还要不断总结经验和技术,分享给大家。

posted @ 2017-08-04 11:09  邵世铨  阅读(273)  评论(0编辑  收藏  举报