ajax调用WCF文件上传,解析form-data数据

        新入职的公司需要做PHP调用WCF服务的接口,然后涉及到导入导出的时候,前端大哥说给我一个form-data的文件流。然后...我就悲催的发现,WCF无法解析form-data,只能自己想办法去处理form-data返回给我的数据流。废话不多说,接下来上思路,上代码。

        大家都知道form-data 的格式,我也不在这里卖弄了。我的设想就是将文件流转成字符串然后解析字符串,截取到文件内容之后,再转为byte[],最后将byte[]转为文件。与此同时,我在CSDN发现一位大神的自定义multipart/form-data的解析器,跟我的想法不谋而合。

有兴趣的朋友可以去看看。

我将大神的代码搬运了一下,并做了自己这边对应需要的修改。

internal class FormdataCase
    {
        /// <summary>
        /// 参数集合
        /// </summary>
        public IDictionary<string, string> Parameters = new Dictionary<string, string>();
        /// <summary>
        /// 是否解析成功
        /// </summary>
        public bool Success { get; private set; }
        /// <summary>
        /// 请求类型
        /// </summary>
        public string ContentType { get; private set; }
        /// <summary>
        /// 上传的文件名
        /// </summary>
        public string Filename { get; private set; }
        /// <summary>
        /// 上传的文件内容
        /// </summary>
        public byte[] FileContents { get; private set; }

        /// <summary>
        /// 解析multipart/form-data格式的文件请求,默认编码为utf8
        /// </summary>
        /// <param name="stream"></param>
        public FormdataCase(Stream stream)
        {
            Parse(stream, Encoding.UTF8);
        }

 这是一个解析类,首先将需要设置的参数这些的字段配置好。参数集合是用来保存form表单的其他参数,毕竟你的form表单中不可能只有一个文件上传。

接下来是对应的Parse方法,以及Parse方法中需要用到的Stream转byte[]和后续截取文件内容所需要的方法。

        /// <summary>
        /// 解析form-data
        /// </summary>
        /// <param name="stream">可带参数,并不是只可以放一个文件</param>
        /// <param name="encoding">utf8</param>
        private void Parse(Stream stream, Encoding encoding)
        {
            Success = false;
 
            var data = ToByteArray(stream);//将文件流转为byte[]
 
            var content = encoding.GetString(data);//将byte[]转为string字符串
 
            var delimiterEndIndex = content.IndexOf("\r\n", StringComparison.Ordinal);
 
            if (delimiterEndIndex > -1)
            {
                var delimiter = content.Substring(0, content.IndexOf("\r\n", StringComparison.Ordinal)).Trim();
 
                var sections = content.Split(new[] {delimiter}, StringSplitOptions.RemoveEmptyEntries);
 
                foreach (var s in sections)
                {
                    if (s.Contains("Content-Disposition"))
                    {
                        //获取form-data中的参数名称
                        var nameMatch = new Regex(@"(?<=name\=\"")(.*?)(?=\"")").Match(s);
                        var name = nameMatch.Value.Trim().ToLower();

                        //这里由于文件的参数名称为file,当获取到参数名称等于 file时,可以将文件内容截取出来,参数不是文件时将该参数存入泛型集合Parameters中。
                        if (name == "file")
                        {
                            var re = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");
                            var contentTypeMatch = re.Match(content);
                            
                            //获取文件名
                            re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
                            var filenameMatch = re.Match(content);
                            
                            //截取文件
                            if (contentTypeMatch.Success && filenameMatch.Success)
                            {
                                ContentType = contentTypeMatch.Value.Trim();
                                Filename = filenameMatch.Value.Trim();
 
                                var startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;
 
                                var delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
                                var endIndex = IndexOf(data, delimiterBytes, startIndex);
 
                                var contentLength = endIndex - startIndex;//计算文件流长度
 
                                var fileData = new byte[contentLength];
 
                                Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
 
                                FileContents = fileData;
                            }
                        }
                        else if (!string.IsNullOrWhiteSpace(name))
                        {
                            //截取非文件参数,并将参数名称与参数值保存在泛型集合Parameters中。
                            var startIndex = nameMatch.Index + nameMatch.Length + "\r\n\r\n".Length;
                            Parameters.Add(name, s.Substring(startIndex).TrimEnd('\r', '\n').Trim());
                        }
                    }
                }
 
                if (FileContents != null || Parameters.Count != 0)
                {
                    Success = true;
                }
            }
        }
        
        /// <summary>
        /// 获取文件流末尾
        /// </summary>
        /// <param name="searchWithin"></param>
        /// <param name="serachFor"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        public static int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex)
        {
            var index = 0;
            var 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(searchWithin, serachFor[0], startPos + index);
                        if (startPos == -1)
                        {
                            return -1;
                        }
 
                        index = 0;
                    }
                }
            }
 
            return -1;
        }
        
        /// <summary>
        /// 将stream转为byte[]
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] ToByteArray(Stream stream)
        {
            var buffer = new byte[32768];
            using (var ms = new MemoryStream())
            {
                while (true)
                {
                    var read = stream.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                    {
                        return ms.ToArray();
                    }
 
                    ms.Write(buffer, 0, read);
                }
            }
        }
    }

代码中每一步我都做了很详细的注释。并且用postman测试之后没有问题,数据保存完好,没有乱码。各位看官如果有用得到以及更好地改进方法,欢迎评论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值