zoukankan      html  css  js  c++  java
  • C# Body为form-data file文件上传至第三方接口

    1.第三方提供了这么一个API接口,POST后将附件以file文件上传,通过postman工具界面是下面这种样子

    Body为form-data类型,不管是文本还是文件,都能在value上填上去

    2.C#实现接口调用代码

    public static string PostForm(string url, List<FormItemModel> formItems, CookieContainer cookieContainer = null, string refererUrl = null, Encoding encoding = null, int timeOut = 20000)
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                #region 初始化请求对象
                request.Method = "POST";
                request.Timeout = timeOut;
                request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
                request.KeepAlive = true;
                request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
                if (!string.IsNullOrEmpty(refererUrl))
                    request.Referer = refererUrl;
                if (cookieContainer != null)
                    request.CookieContainer = cookieContainer;
                #endregion
    
                string boundary = "----" + DateTime.Now.Ticks.ToString("x");//分隔符
                request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
                //请求流
                var postStream = new MemoryStream();
                #region 处理Form表单请求内容
                //是否用Form上传文件
                var formUploadFile = formItems != null && formItems.Count > 0;
                if (formUploadFile)
                {
                    //文件数据模板
                    string fileFormdataTemplate =
                        "
    --" + boundary +
                        "
    Content-Disposition: form-data; name="{0}"; filename="{1}"" +
                        "
    Content-Type: application/octet-stream" +
                        "
    
    ";
                    //文本数据模板
                    string dataFormdataTemplate =
                        "
    --" + boundary +
                        "
    Content-Disposition: form-data; name="{0}"" +
                        "
    
    {1}";
                    foreach (var item in formItems)
                    {
                        string formdata = null;
                        if (item.IsFile)
                        {
                            //上传文件
                            formdata = string.Format(
                                fileFormdataTemplate,
                                item.Key, //表单键
                                item.FileName);
                        }
                        else
                        {
                            //上传文本
                            formdata = string.Format(
                                dataFormdataTemplate,
                                item.Key,
                                item.Value);
                        }
    
                        //统一处理
                        byte[] formdataBytes = null;
                        //第一行不需要换行
                        if (postStream.Length == 0)
                            formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2));
                        else
                            formdataBytes = Encoding.UTF8.GetBytes(formdata);
                        postStream.Write(formdataBytes, 0, formdataBytes.Length);
    
                        //写入文件内容
                        if (item.FileContent != null && item.FileContent.Length > 0)
                        {
                            using (var stream = item.FileContent)
                            {
                                byte[] buffer = new byte[1024];
                                int bytesRead = 0;
                                while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
                                {
                                    postStream.Write(buffer, 0, bytesRead);
                                }
                            }
                        }
                    }
                    //结尾
                    var footer = Encoding.UTF8.GetBytes("
    --" + boundary + "--
    ");
                    postStream.Write(footer, 0, footer.Length);
    
                }
                else
                {
                    request.ContentType = "application/x-www-form-urlencoded";
                }
                #endregion
    
                request.ContentLength = postStream.Length;
    
                #region 输入二进制流
                if (postStream != null)
                {
                    postStream.Position = 0;
                    //直接写入流
                    Stream requestStream = request.GetRequestStream();
    
                    byte[] buffer = new byte[1024];
                    int bytesRead = 0;
                    while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        requestStream.Write(buffer, 0, bytesRead);
                    }
    
                    ////debug
                    //postStream.Seek(0, SeekOrigin.Begin);
                    //StreamReader sr = new StreamReader(postStream);
                    //var postStr = sr.ReadToEnd();
                    postStream.Close();//关闭文件访问
                }
                #endregion
    
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                if (cookieContainer != null)
                {
                    response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
                }
    
                using (Stream responseStream = response.GetResponseStream())
                {
                    using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.UTF8))
                    {
                        string retString = myStreamReader.ReadToEnd();
                        return retString;
                    }
                }
            }
    
    
    public class FormItemModel
        {
            /// <summary>
            /// 表单键,request["key"]
            /// </summary>
            public string Key { set; get; }
            /// <summary>
            /// 表单值,上传文件时忽略,request["key"].value
            /// </summary>
            public string Value { set; get; }
            /// <summary>
            /// 是否是文件
            /// </summary>
            public bool IsFile
            {
                get
                {
                    if (FileContent == null || FileContent.Length == 0)
                        return false;
    
                    if (FileContent != null && FileContent.Length > 0 && string.IsNullOrWhiteSpace(FileName))
                        throw new Exception("上传文件时 FileName 属性值不能为空");
                    return true;
                }
            }
            /// <summary>
            /// 上传的文件名
            /// </summary>
            public string FileName { set; get; }
            /// <summary>
            /// 上传的文件内容
            /// </summary>
            public Stream FileContent { set; get; }
    
    
    
        }
    

    模拟post调用

    var url = "http://127.0.0.1/testformdata.aspx?aa=1&bb=2&ccc=3";
    var log1=@"D:	emplog1.txt";
    var log2 = @"D:	emplog2.txt";
    var formDatas = new List<Grass.Net.FormItemModel>();
    //添加文件
    formDatas.Add(new Grass.Net.FormItemModel()
    {
        Key="log1",
        Value="",
        FileName = "log1.txt",
        FileContent=File.OpenRead(log1)
    });
    formDatas.Add(new Grass.Net.FormItemModel()
    {
        Key = "log2",
        Value = "",
        FileName = "log2.txt",
        FileContent = File.OpenRead(log2)
    });
    //添加文本
    formDatas.Add(new Grass.Net.FormItemModel()
    {
        Key = "id",
        Value = "id-test-id-test-id-test-id-test-id-test-"
    });
    formDatas.Add(new Grass.Net.FormItemModel()
    {
        Key = "name",
        Value = "name-test-name-test-name-test-name-test-name-test-"
    });
    //提交表单
    var result = PostForm(url, formDatas);
    

    至此引用别人的资料:https://www.cnblogs.com/xiaosuxing/p/13403172.html

    3.以上方法读流是通过文件存取的绝对路径去转换为流,进而去请求第三方接口把文件以流的方式上传
    如果是文件服务器上的URL,则此方法不能通用,也试过将流转换都不行,最后找到一种思路可行,先将URL下载存到临时文件夹里,再通过以上方法将文件读取成流后上传,代码如下

    /// <summary>
            ///  根据文件服务器上的地址URL保存文件到临时路径
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            public static Stream HttpDownload(string url)
            {
                using (var client = new WebClient())
                {
                    string tempFile = Path.GetTempFileName();
                    client.DownloadFile(url, tempFile);//下载临时文件
                    return FileToStream(tempFile, true);//转文件流后删除临时文件夹
                }
            }
    
            /// <summary>
            /// 文件转流
            /// </summary>
            /// <param name="fileName">文件路径</param>
            /// <param name="isDelete">是否删除临时文件</param>
            /// <returns></returns>
            public static Stream FileToStream(string fileName, bool isDelete = false)
            {
    
                //打开文件
    
                FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
    
                // 读取文件的 byte[]
    
                byte[] bytes = new byte[fileStream.Length];
    
                fileStream.Read(bytes, 0, bytes.Length);
    
                fileStream.Close();
    
                // 把 byte[] 转换成 Stream
    
                Stream stream = new MemoryStream(bytes);
                if (isDelete)
                {
                    File.Delete(fileName);//删除临时文件
                }
                return stream;
    
            }
    
    人说,如果你很想要一样东西,就放它走 。如果它回来找你,那么它永远都是你的。要是它没有回来,那么不用再等了,因为它根本就不是你的。 ——伊恩·麦克尤恩 ​
  • 相关阅读:
    SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSAS 系列
    微软BI 之SSRS 系列
    微软BI 之SSRS 系列
    配置 SQL Server Email 发送以及 Job 的 Notification通知功能
  • 原文地址:https://www.cnblogs.com/ButterflyEffect/p/14773840.html
Copyright © 2011-2022 走看看