最近把套接字发送图片功能完成了,其间如何发送图片及遇到了很多问题,在此将其列出以作参考:
发送图片思路:获得图片路径,然后将路径读取成字节流组,接下来把图片转换成base64的字符串,然后将这个base64的字符串通过JsonConvert序列化(其实这里没必要序列化,主要是服务器接收图片的字节流时无法确定该字节流大小所以一般会给一个10000+的大小(目前不考虑图片分组发送),但是这样很容易让规定的字节流组很多浪费,所以一开始就base64将图片里面有0的字节也变成字符串然后序列化成字节流组发送,这样服务器接收的字节流组的有效信息没有0的,然后此时就可以放心的把自己规定的10000+的大小字节组浪费的部分全部remove 0,然后移除后的字节流组也就全是有效信息了),然后服务器接收的字节流组先把它反序列化,然后frombase64成字节流组(这是真正的图片的流信息),接着
MemoryStream SavaImg = new MemoryStream();//实例化内存流
SavaImg.Write(ContentByte, 0, ContentByte.Length);//将图片字节组(ContenByte)从头到尾放进这个内存流中
SavaImg.Position = 0;//令读取位置回到0,防止之后读取值错误
Bitmap bitmap = new Bitmap(SavaImg);//然后把该内存流放进bitmap里面
Clipboard.SetDataObject(bitmap, false, 5, 10);//将图片的流信息放入剪贴板,程序关闭后信息不保存在剪贴板,如果失败则每个 //10秒就去再放进剪贴板,此动作重复5次
richTextBox1.Invoke((Action)delegate//因为我是不同线程去访问这个控件,所以必须回调(详细百度)
{
if (richTextBox1.CanPaste(DataFormats.GetFormat(DataFormats.Bitmap)))//如果该富文本框能粘贴(图片信息无损) //就执行if里面语句
{
richTextBox1.Paste(DataFormats.GetFormat(DataFormats.Bitmap));//将信息粘贴到富文本框 //(richTextBox1.Paste())即可
richTextBox1.ScrollToCaret();
}
});
Clipboard.Clear();//剪贴板清除
这样图片就完成了,当然这只是单线程里面,代码不会是单线程一般是多线程的,所以问题就来了:
问题1:我现在要图文一起发送
解决:因为目前技术不高,所以只有采用对文字进行加头尾(240),图片(250),240、250是放进字节组里面,如:文字变成字节组后应该是:240 34 25 60 96 45 34 240 (其中34是序列化的不用管,里面的就是文本内容,同理图片如此,不过图片字节流组很大哦)。
问题二:当我单个发送图片时,发送第一张图片能正常显示然后第二张图片发后出现第一张消失只有第二张图片。当我发送文字图片,第一次发送正常显示,第二次只有文字而第一张图片消失只有第二张图片。当我发送图片文字,不论次数都只有文字。
解决:首先,我们得去看看服务器接收的客户端发来的图片是否受损了(frombase64的字节流组,可以对比客户端发的还未base64的字节流组),如果没问题说明很可能是剪贴板出问题了,因为图片是format上去的,所以自己发的文字都必须format不能richtextbox1.text += Content(发送的文字内容);必须richTextBox1.AppendText(string.Format("{0}", Content)); 这样就没问题。
问题三:因为多线程问题,会出现打开对话框报错STA,或者是剪贴板报错STA(两者都遇到了,他们必须单线程运行也就是必须STA线程)
解决:
// 打开对话框的委托
public delegate void richtextbox();
public void getRichBox()
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Title = "选择图片";
openFile.Filter = "所有文件(*.*)|*.*";
openFile.Multiselect = false;
if (openFile.ShowDialog() == DialogResult.OK)
{
//注意:这是演示对话框处理,剪贴板同样但是需注意一点,当这个方法是STA线程运行时然后里面又是invoke那么此 时STA没
//作用,请将 代码写在回调外面!!
//如: Clipboard.SetDataObject(bitmap, false, 5, 10);
richTextBox2.Invoke((Action)delegate
{
richTextBox2.AppendText("[Img:" + openFile.FileName + "]");
});
}
}
//获取图片
public void toolStripButton3_Click(object sender, EventArgs e)
{
try
{
richtextbox richtextbox1 = new richtextbox(getRichBox);
Thread recvThread = new Thread(new ThreadStart(richtextbox1));
//必须STA单线程调用
recvThread.SetApartmentState(ApartmentState.STA);
recvThread.Start();
}
catch (Exception ex)
{
throw new Exception("出错啦!", ex);
}
}错误演示图片忘记截图了,以下是功能完成图: