c# MVC下文件下载后Memorystream上传到别的服务器出问题解决方案

需求是从微信通过media_id去下载图片到MemoryStream,然后将该MemoryStream直接上传到自己的服务器保存。


        

/// <summary>
        /// 下载多媒体文件
        /// </summary>
        /// <param name="media_id">多媒体ID</param>
        /// <param name="asToken"></param>
        /// <returns></returns>
        public Stream download_img(string media_id, string asToken, out string err)
        { 
            err="";
            try
            {
                Stream retStream = KisCommon.GetDownLoadFile("http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + asToken + "&media_id=" + media_id);
                return retStream;
            }
            catch(Exception ex)
            {
                err = ex.Message;
            }


            return null;
        }

        public static Stream GetDownLoadFile(String url)
        {
            WebRequest request = WebRequest.Create(url);
            WebResponse response = request.GetResponse();
            Stream reader = response.GetResponseStream();
            Stream retStream = new MemoryStream();
            byte[] buff = new byte[512];
            int c = 0; //实际读取的字节数
            while ((c = reader.Read(buff, 0, buff.Length)) > 0)
            {
                retStream.Write(buff, 0, c);
            }
            reader.Close();
            reader.Dispose();
            response.Close();


            return retStream;
        }

结果发现下载后的MemoryStream死活不能上传上去

 /// <summary>
        /// 将本地文件上传到指定的服务器(HttpWebRequest方法)
        /// </summary>
        /// <param name="address">文件上传到的服务器</param>
        /// <param name="stream">要上传的文件流</param>
        /// <param name="saveName">文件上传后的名称</param>
        /// <returns>返回结果</returns>
        public static string Upload_Request(string address, Stream stream, string saveName)
        {
            // 要上传的文件
            BinaryReader r = new BinaryReader(stream);
            //时间戳
            string strBoundary = "----------" + DateTime.Now.Ticks.ToString("x");
            byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + strBoundary + "\r\n");
            //请求头部信息
            StringBuilder sb = new StringBuilder();
            sb.Append("--");
            sb.Append(strBoundary);
            sb.Append("\r\n");
            sb.Append("Content-Disposition: form-data; name=\"");
            sb.Append("newfile");
            sb.Append("\"; filename=\"");
            sb.Append(saveName);
            sb.Append("\"");
            sb.Append("\r\n");
            sb.Append("Content-Type: ");
            sb.Append("application/octet-stream");
            sb.Append("\r\n");
            sb.Append("\r\n");
            string strPostHeader = sb.ToString();
            byte[] postHeaderBytes = Encoding.UTF8.GetBytes(strPostHeader);
            // 根据uri创建HttpWebRequest对象
            HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(new Uri(address));
            httpReq.Method = "POST";
            //对发送的数据不使用缓存
            httpReq.AllowWriteStreamBuffering = true;
            //设置获得响应的超时时间(300秒)
            httpReq.Timeout = 300000;
            httpReq.ContentType = "multipart/form-data; boundary=" + strBoundary;
            long length = stream.Length + postHeaderBytes.Length + boundaryBytes.Length;
            long fileLength = stream.Length;
            httpReq.ContentLength = length;
            try
            {
                //每次上传4k
                int bufferLength = 4096;
                byte[] buffer = new byte[bufferLength];
                //已上传的字节数
                long offset = 0;
                //开始上传时间
                DateTime startTime = DateTime.Now;
                int size = r.Read(buffer, 0, bufferLength);
                Stream postStream = httpReq.GetRequestStream();
                //发送请求头部消息
                postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
                while (size > 0)
                {
                    postStream.Write(buffer, 0, size);
                    offset += size;
                    size = r.Read(buffer, 0, bufferLength);
                }
                //添加尾部的时间戳
                postStream.Write(boundaryBytes, 0, boundaryBytes.Length);
                postStream.Close();
                //获取服务器端的响应
                WebResponse webRespon = httpReq.GetResponse();
                Stream s = webRespon.GetResponseStream();
                StreamReader sr = new StreamReader(s);
                //读取服务器端返回的消息
                String sReturnString = sr.ReadLine();
                s.Close();
                sr.Close();

                return sReturnString;

            }
            catch (Exception ex)
            {

            }
            finally
            {
                r.Close();
            }
            return "";
        }
上面代码上,断点发现读取的size都是0,很疑惑,图片数据明明就在MemoryStream中了,但是就是上传失败。后来尝试用FileStream来保存文件,再读取上传却一切正常,不过使用FileStream管理起来非常麻烦,而且占用空间。


于是乎我把MemoryStream和FileStream的内容作了比较,发现Lenth完全一致,说明内容没有差别,但是FileStream的Position为0(字节位移),而MemoryStream的Position和lenth一致,恍然大悟!

r.Read(buffer, 0, bufferLength);Stream的读取和写入操作都是从Position开始操作的,当下载的时候,MemoryStream由于不断的写入,Position一直等于MemoryStream的Lenth,所以当读取的时候,由于Position一直在最高位,读取不出任何的东西!


所以在上传之前,只需要将MemoryStream的Position置0,就能正常上传了!

<span style="font-family: Arial, Helvetica, sans-serif;"></span>


你可能感兴趣的:(c# MVC下文件下载后Memorystream上传到别的服务器出问题解决方案)