I want to send a message and photo to a channel with my bot in c# 2013, but I'm getting The remote server returned an error: (400) Bad Request
I want to send a message and photo to a channel with my bot in c# 2013, but I'm getting The remote server returned an error: (400) Bad Request
我想在 c# 2013 中使用我的机器人向频道发送消息和照片。
消息和照片应该在一个盒子里发送。照片在消息上方。
我可以成功向频道发送消息,但是有两个问题:
- 发送照片时,出现此错误:
The remote server returned an error: (400) Bad Request.
- 我无法在一次发送中将文字和照片一起发送。
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Telegram.Bot;
using Telegram.Bot.Types;
using System.Net;
namespace SendTxt-Photo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string Token = "adasdsadsadsadasds";
string channel_id = "@BestLaptop";
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
using (var stream = File.Open(@"image/1.jpg", FileMode.Open))
{
WebRequest req = WebRequest.Create("https://api.telegram.org/bot" + Token + "/sendMessage?chat_id=" + channel_id + "&text=" + textbox1.text);
req.UseDefaultCredentials = true;
WebRequest req1 = WebRequest.Create("https://api.telegram.org/bot" + Token + "/sendPhoto?chat_id=" + channel_id + "&Photo=" + stream );
req.UseDefaultCredentials = true;
req1.UseDefaultCredentials = true;
var result = req.GetResponse();
req.Abort();
var result1 = req1.GetResponse();
req1.Abort();
}
}
}
}
首先您必须知道您发送的是...&photo=Sistem.IO.FileStream
而不是您的文件。这是错误请求的根本原因。在调试中查看。
第二个正如你在api documentation中看到的sendPhoto
方法提供了三种类型的photo
参数:
Pass a file_id as String to send a photo that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a photo from the Internet, or upload a new photo using multipart/form-data.
所以根据您的情况需要使用 multipart/form-data
。可以用RestSharp for example like (code was generated by Postman简化,没测试过):
var client = new RestClient("https://api.telegram.org/botadasdsadsadsadasds/sendPhoto");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"chat_id\"\r\n\r\n@BestLaptop\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"1.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
在第三个,您不能在一条消息中的文字上方发送照片。要在一条消息中发送文本和照片,请使用 sendPhoto
方法的 caption
参数。它提供 200 个符号长度。
PS 为什么不使用 Telegram.Bot nuget 包?
此函数是上传文件的助手:
public static string UploadFilesToRemoteUrl(HttpWebRequest request, string[] files, NameValueCollection formFields = null)
{
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
request.KeepAlive = true;
Stream memStream = new System.IO.MemoryStream();
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "\r\n");
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "--");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
if (formFields != null)
{
foreach (string key in formFields.Keys)
{
string formitem = string.Format(formdataTemplate, key, formFields[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
}
}
string headerTemplate =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
for (int i = 0; i < files.Length; i++)
{
memStream.Write(boundarybytes, 0, boundarybytes.Length);
var header = string.Format(headerTemplate, "photo", files[i]);
var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
{
var buffer = new byte[1024];
var bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
}
}
memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
request.ContentLength = memStream.Length;
using (Stream requestStream = request.GetRequestStream())
{
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
}
using (var response = request.GetResponse())
{
Stream stream2 = response.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
return reader2.ReadToEnd();
}
}
这里是发送文件的代码(用于 Roscomnadzor 的代理)使用你的变量而不是 msg.GetParam({""}) 你需要 chat_id, bot_id,photo和标题。如果你需要,"proxy"。
string filePath = msg.GetParam("photo");
string URL = "https://api.telegram.org/bot" + msg.GetParam("bot_id") + "/sendPhoto";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
WebProxy myProxy = new WebProxy(msg.GetParam("proxy"));
myProxy.UseDefaultCredentials = true;
request.Proxy = myProxy;
string[] variable_name = {filePath};
NameValueCollection form = new NameValueCollection();
form["chat_id"] = msg.GetParam("chat_id");
form["caption"] = msg.GetParam("caption");
UploadFilesToRemoteUrl(request, variable_name, form);
我想在 c# 2013 中使用我的机器人向频道发送消息和照片。 消息和照片应该在一个盒子里发送。照片在消息上方。
我可以成功向频道发送消息,但是有两个问题:
- 发送照片时,出现此错误:
The remote server returned an error: (400) Bad Request.
- 我无法在一次发送中将文字和照片一起发送。
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Telegram.Bot;
using Telegram.Bot.Types;
using System.Net;
namespace SendTxt-Photo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string Token = "adasdsadsadsadasds";
string channel_id = "@BestLaptop";
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
using (var stream = File.Open(@"image/1.jpg", FileMode.Open))
{
WebRequest req = WebRequest.Create("https://api.telegram.org/bot" + Token + "/sendMessage?chat_id=" + channel_id + "&text=" + textbox1.text);
req.UseDefaultCredentials = true;
WebRequest req1 = WebRequest.Create("https://api.telegram.org/bot" + Token + "/sendPhoto?chat_id=" + channel_id + "&Photo=" + stream );
req.UseDefaultCredentials = true;
req1.UseDefaultCredentials = true;
var result = req.GetResponse();
req.Abort();
var result1 = req1.GetResponse();
req1.Abort();
}
}
}
}
首先您必须知道您发送的是...&photo=Sistem.IO.FileStream
而不是您的文件。这是错误请求的根本原因。在调试中查看。
第二个正如你在api documentation中看到的sendPhoto
方法提供了三种类型的photo
参数:
Pass a file_id as String to send a photo that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a photo from the Internet, or upload a new photo using multipart/form-data.
所以根据您的情况需要使用 multipart/form-data
。可以用RestSharp for example like (code was generated by Postman简化,没测试过):
var client = new RestClient("https://api.telegram.org/botadasdsadsadsadasds/sendPhoto");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"chat_id\"\r\n\r\n@BestLaptop\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"1.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
在第三个,您不能在一条消息中的文字上方发送照片。要在一条消息中发送文本和照片,请使用 sendPhoto
方法的 caption
参数。它提供 200 个符号长度。
PS 为什么不使用 Telegram.Bot nuget 包?
此函数是上传文件的助手:
public static string UploadFilesToRemoteUrl(HttpWebRequest request, string[] files, NameValueCollection formFields = null)
{
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
request.KeepAlive = true;
Stream memStream = new System.IO.MemoryStream();
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "\r\n");
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "--");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
if (formFields != null)
{
foreach (string key in formFields.Keys)
{
string formitem = string.Format(formdataTemplate, key, formFields[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
}
}
string headerTemplate =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
for (int i = 0; i < files.Length; i++)
{
memStream.Write(boundarybytes, 0, boundarybytes.Length);
var header = string.Format(headerTemplate, "photo", files[i]);
var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
{
var buffer = new byte[1024];
var bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
}
}
memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
request.ContentLength = memStream.Length;
using (Stream requestStream = request.GetRequestStream())
{
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
}
using (var response = request.GetResponse())
{
Stream stream2 = response.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
return reader2.ReadToEnd();
}
}
这里是发送文件的代码(用于 Roscomnadzor 的代理)使用你的变量而不是 msg.GetParam({""}) 你需要 chat_id, bot_id,photo和标题。如果你需要,"proxy"。
string filePath = msg.GetParam("photo");
string URL = "https://api.telegram.org/bot" + msg.GetParam("bot_id") + "/sendPhoto";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
WebProxy myProxy = new WebProxy(msg.GetParam("proxy"));
myProxy.UseDefaultCredentials = true;
request.Proxy = myProxy;
string[] variable_name = {filePath};
NameValueCollection form = new NameValueCollection();
form["chat_id"] = msg.GetParam("chat_id");
form["caption"] = msg.GetParam("caption");
UploadFilesToRemoteUrl(request, variable_name, form);