首页 新闻 会员 周边

用C#保存来自IOS发送的图片流

1
悬赏园豆:50 [已解决问题] 解决于 2015-01-06 19:31

在做一个IOS把图片上传到服务器的小功能
IOS用的是AFNETWORKing写的图片流上传,代码如下

NSString *filename=@"test.jpg";
AFHTTPRequestOperationManager *AFManager=[[AFHTTPRequestOperationManager alloc]initWithBaseURL:[NSURL URLWithString:@FileTranUrl]];
AFHTTPRequestOperation *operation=[AFManager POST:path parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formdata){[formdata appendPartWithFileData:imagedata name:name fileName:filename mimeType:@"image/jpeg"];} success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
success(operation,responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) {
failure(operation,error);
}
}];

 

从代码中可以看出AFNetwork将图片数据,图片名称和该数据名称都传入了网络流中,我直接用C#直接将获得流保存的话生成的图片无法打开
C#主要代码

using (targetStream = new FileStream(filePathAndName, FileMode.Create, FileAccess.Write, FileShare.None))
{
const int bufferLen = 4096;
Byte[] buffer = new Byte[bufferLen];
int count = 0;

while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
targetStream.Write(buffer, 0, count);
filesize += count;
}
targetStream.Close();
sourceStream.Close();


} 

 


我用Notepad++打开以文件流保存的这个文件,可以清楚的看到流的开头正是AFNetwork给发送的参数:

--Boundary+3064FAAD3A74E02F
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg

??JFIF  H H (这里是乱码了,应该是图片的数据部分了)

结尾--Boundary+3064FAAD3A74E02F--

现在的问题来了,从ios发过的流既包含该文件的格式,文件名等也保含了文件的数据,我查了很多C#关于流的操作,没有发现可以分开处理的,不知道你们是怎么解决的呢?
上传图片的最后一步了,我卡主了好久了。。。。

KeithMorning的主页 KeithMorning | 初学一级 | 园豆:161
提问于:2015-01-05 02:23
< >
分享
最佳答案
1

终于被我解决了,基本方式是正则表达式匹配里面key如content-type,filename,匹配完后从后面都是图片流的数据,直接写就可以了,这样可以保存从ios端发来的文件名称和文件格式,其实这样已经实现保存ios发来的任何文件,不止包括图片格式

这是我在stackflow的提问原题。希望可以帮助碰到相同问题的朋友。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace WcfServiceForIOS.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; }
    }

}   
View Code

如果是单个文件,调用的时候使用filename和filecontent就可以了

最后提醒一下,记得stream.close();传过来的和声明的filestream都需要关闭。

KeithMorning | 初学一级 |园豆:161 | 2015-01-05 10:33

 public MultipartParser(Stream stream)
        {
            this.Parse(stream, Encoding.UTF8);
         //   ParseParameter(stream, Encoding.UTF8);
        }

        public MultipartParser(Stream stream, Encoding encoding)
        {
            this.Parse(stream, encoding);
        }

这个流文件: public MultipartParser(Stream stream) 是怎么获取的

唯我独萌 | 园豆:537 (小虾三级) | 2015-09-16 10:44

@背叛的冲刷:  HttpFileCollection collection = HttpContext.Current.Request.Files;是这样吗

唯我独萌 | 园豆:537 (小虾三级) | 2015-09-16 10:45
其他回答(3)
0

你是把整个请求保存下来了。你应该从请求里获取文件保存下来

收获园豆:50
吴瑞祥 | 园豆:29449 (高人七级) | 2015-01-05 09:26
0

转成base64字符串,然后C#端转回存就是了,比你文件流好多了

冲杀 | 园豆:230 (菜鸟二级) | 2015-01-09 13:37

亲,这个有例子么,主要是ios向C#服务器传递那里,和C#服务器端接收那里,有没有简洁的代码,ios可以直接向服务器传递字节流么,还是转换为base64比较好

支持(0) 反对(0) tiger逸 | 园豆:200 (初学一级) | 2015-05-21 10:54
0

怎么样用?我是用的是下面的方法调用的,都在UploadImgByWebService里处理,麻烦发个例子。244282742@qq.com

zhangzhenpeng | 园豆:202 (菜鸟二级) | 2015-06-25 17:01
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册