web api 如何通过接收文件流的方式,接收客户端及前端上传的文件

 

服务端接收文件流代码:

        public async Task<HttpResponseMessage> ReceiveFileByStream()
        {
            var stream = HttpContext.Current.Request.InputStream;
            if (stream.Length > 0)
            {
                var absolutePath = HttpContext.Current.Request.MapPath("/img/");
                if (!Directory.Exists(absolutePath))
                {
                    Directory.CreateDirectory(absolutePath);
                }
                var fileType = "";
                var bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                //前两个字节代表文件类型,这里以 JPG 类型为例
                var bs = bytes[0].ToString() + bytes[1].ToString();
                if (bs.Equals("255216"))
                {
                    fileType = ".jpg";
                }
                var path = absolutePath + Guid.NewGuid() + fileType;
                await Task.Run(() =>
                {
                    using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
                    {
                        fs.Write(bytes, 0, bytes.Length);
                    }
                });
                return Request.CreateResponse(HttpStatusCode.OK, "上传成功!");
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "没有文件耶,哥们!");
            }
        }

 

客户端上传文件流代码:

HttpClient

        static string TestHttpClientUpload()
        {
            var resultStr = string.Empty;
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("http://192.168.20.15:57895");
            string apiUrl = "api/upload/ReceiveFileByStream";
string path = @"C:\Users\xxxx\Desktop\woman.jpg"; FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
HttpContent content
= new StreamContent(fs); var result = client.PostAsync(apiUrl, content).Result; fs.Dispose(); resultStr = result.Content.ReadAsStringAsync().Result; return resultStr;//上传成功 }

 

HttpWebRequest 

        static string TestHttpWebRequestUpload()
        {
            var resultStr = string.Empty;
            string url = "http://192.168.20.15:57895/api/upload/ReceiveFileByStream";
            HttpWebRequest request = WebRequest.CreateHttp(url);
            request.Method = "post";

            string path = @"C:\Users\xxxx\Desktop\woman.jpg";
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
            var requestStream = request.GetRequestStream();
            fs.CopyTo(requestStream);
            fs.Dispose();
            requestStream.Dispose();

            var result = request.GetResponseAsync().Result;
            var responseStream = result.GetResponseStream();
            using (StreamReader sm = new StreamReader(responseStream))
            {
                resultStr = sm.ReadToEnd();
            }
            return resultStr;//上传成功
        }

 

前端上传文件:

    <div>
        <span>Form表单上传单个文件</span><br />
        <form id="myForm1" enctype="multipart/form-data" method="post" action="http://192.168.20.15:57895/api/upload/ReceiveFileByStream">
            <input type="file" name="myFile" />
            <input type="submit" value="submit提交" />
        </form>
    </div>

 

上面三种方式,客户端没有问题,但是前端这样上传是有问题的,因为在文件流开头还有其他东西:

用一段代码测试:

                //这里的 255 是 255216 里面的 255, 从 255 所在的位置开始才是文件的字节数据
                var index = bytes.ToList().IndexOf(255);
                var str = Encoding.UTF8.GetString(bytes, 0, index);
                Trace.WriteLine(str);

这就是HTTP请求自带的,打开浏览器,F12,可以看到:

那么,如何成功的躲避这一段字节呢?

答案是 : 利用 Ajax 提交表单

    <div>
        <form id="myForm4">
            <input type="file" id="myFile" />
            <input type="button" value="AJAX提交图片" onclick="uploadFile()" />
        </form>
    </div>

 

        function uploadFile() {
            var url = "http://192.168.20.15:57895/api/upload/ReceiveFileByStream";
            var data = $("#myFile")[0].files[0];
            $.ajax({
                url: url,
                data: data,
                type: "post",
                processData: false,//表示提交的时候不会序列化 data,而是直接使用 data,默认为 true
                contentType: false,//表示不要去设置Content-Type请求头
                cache: false,//设置为 false 将不会从浏览器缓存中加载请求信息。
                success: function () { }
            });
        }

 

但是,这样提交在跨域的时候,会有一次 OPTIONS 请求

 

下面那次请求才是 POST 请求,至于为什么会有一次 OPTIONS 请求,大家可以自行百度,这里就不说了.

那么如何成功的避免这次 OPTIONS 请求呢?

答案就是 : Ajax 请求的时候, 不设置  contentType 属性!

        function uploadFile() {
            var url = "http://192.168.20.15:57895/api/upload/ReceiveFileByStream";
            var data = $("#myFile")[0].files[0];
            $.ajax({
                url: url,
                data: data,
                type: "post",
                processData: false,//表示提交的时候不会序列化 data,而是直接使用 data,默认为 true
                cache: false,//设置为 false 将不会从浏览器缓存中加载请求信息。
                success: function () { }
            });
        }

 

收工!

posted @ 2018-03-09 16:56  热敷哥  阅读(2871)  评论(1编辑  收藏  举报