C#、python企业微信群机器人自动发送文件

  1. 基本HTTP POST发送方式

  • 表单提交协议规定:
    要先将 HTTP 要求的 Content-Type 设为 multipart/form-data,而且要设定一个 boundary 参数,
    这个参数是由应用程序自行产生,它会用来识别每一份资料的边界 (boundary),
    用以产生多重信息部份 (message part)。
    而 HTTP 服务器可以抓取 HTTP POST 的信息,
    基本内容:
    1. 每个信息部份都要用 --[BOUNDARY_NAME] 来包装,以分隔出信息的每个部份,而最后要再加上一个 --[BOUNDARY_NAME] 来表示结束。
    2. 每个信息部份都要有一个 Content-Disposition: form-data; name="",而 name 设定的就是 HTTP POST 的键值 (key)。
    3. 声明区和值区中间要隔两个新行符号(\r\n)。
    4. 中间可以夹入二进制资料,但二进制资料必须要格式化为二进制字符串。
    5. 若要设定不同信息段的资料型别 (Content-Type),则要在信息段内的声明区设定。

  • 因此两个form内容模板为
    boundary = "----" + DateTime.Now.Ticks.ToString("x");//程序生成
    1.文本内容
    "\r\n--" + boundary +
    "\r\nContent-Disposition: form-data; name=\"键\"; filename=\"文件名\"" +
    "\r\nContent-Type: application/octet-stream" +
    "\r\n\r\n";
    2.文件内容
    "\r\n--" + boundary +
    "\r\nContent-Disposition: form-data; name=\"键\"" +
    "\r\n\r\n内容";

  • Python方法

def upload_file(file_path, wx_upload_url):
    file_name = file_path.split("/")[-1]
    with open(file_path, 'rb') as f:
        length = os.path.getsize(file_path)
        data = f.read()
    headers = {"Content-Type": "application/octet-stream"}
    params = {
        "filename": file_name,
        "filelength": length,
    }
    file_data = copy(params)
    file_data['file'] = (file_path.split('/')[-1:][0], data)
    encode_data = encode_multipart_formdata(file_data)
    file_data = encode_data[0]
    headers['Content-Type'] = encode_data[1]
    print(headers)

    r = requests.post(wx_upload_url, data=file_data, headers=headers)
    print(r.text)
    media_id = r.json()['media_id']
    return media_id


# media_id 通过上一步上传的方法获得
def qi_ye_wei_xin_file(wx_url, media_id):
    headers = {"Content-Type": "text/plain"}
    data = {
        "msgtype": "file",
        "file": {
            "media_id": media_id
        }
    }
    r = requests.post(
        url=wx_url,
        headers=headers, json=data)
  • C#实现方式

  •    class FormItemModel
        {
            /// 
            /// 表单键,request["key"]
            /// 
            public string Key { set; get; }
            /// 
            /// 表单值,上传文件时忽略,request["key"].value
            /// 
            public string Value { set; get; }
            /// 
            /// 是否是文件
            /// 
            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;
                }
            }
            /// 
            /// 上传的文件名
            /// 
            public string FileName { set; get; }
            /// 
            /// 上传的文件内容
            /// 
            public byte[] FileContent { set; get; }
        }
    
    
            public static string PostForm(string url, List 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 =
                        "\r\n--" + boundary +
                        "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" +
                        "\r\nContent-Type: application/octet-stream" +
                        "\r\n\r\n";
                    //文本数据模板
                    string dataFormdataTemplate =
                        "\r\n--" + boundary +
                        "\r\nContent-Disposition: form-data; name=\"{0}\"" +
                        "\r\n\r\n{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)
                        {
                            postStream.Write(item.FileContent, 0, item.FileContent.Length);
                        }
                    }
                    //结尾
                    var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
                    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);
                    }
                    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 static string Send_file(string Url, string media_id)
            {
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(Url);
                req.Method = "POST";
                req.ContentType = "application/octet-stream";//设置对应的ContentType
                string postdata = "{\"msgtype\": \"file\",\"file\": {\"media_id\":\""+ media_id+"\"}}";
                byte[] data = Encoding.UTF8.GetBytes(postdata);//把字符串转换为字节
    
                Stream writer = req.GetRequestStream();//获取
                writer.Write(data, 0, data.Length);
                writer.Flush();
                HttpWebResponse response = (HttpWebResponse)req.GetResponse();//获取服务器返回的结果
                Stream getStream = response.GetResponseStream();
                StreamReader streamreader = new StreamReader(getStream);
                String result = streamreader.ReadToEnd();
                return result;
            }
    

  • 上传文档成功截图

C#、python企业微信群机器人自动发送文件_第1张图片

你可能感兴趣的:(c#,python,开发语言)