所有语言的http服务器上传和下载图片通用要点(Poco C++)


前言

  在很多时候,我们开发http后端服务器都需要在前端和后端之间传输图片,本文将介绍http服务器传输图片时的技术要点。


一、浏览器上传图片

  一般的浏览器上传图片均是使用multipart/form-data的Content-Type进行图片的传输,当然这种类型不仅仅是用于传图片,也用于传输任意文件。html网页使用的代码如下:

<form method="POST" action="http://你的网站的接口" enctype="multipart/form-data">
	<input type="file" name="file" size="31"> 
	<input type="submit" value="Upload">
</form>

  http服务器收到的数据可以使用wireshark来进行抓包分析,收到的request如下:


  http服务器处理的要点时,找到你使用的语言构建的服务器是如何处理HTMLForm 的,HTMLForm 不同于JSON或者url附带的参数,需要进行特别处理。HTMLForm里面有Content-Disposition: form-data; name=“file”; filename=“2.jpg”  用来描述上传的文件的名字。还有一个Content-Type: image/jpeg  属性用来描述文件的类型。HTMLForm使用浏览器指定的边界符号Boundary: "----WebKitFormBoundary85RVxRKo9Q6jwEKL"来确认文件的边界。不同的框架对HTMLForm的处理不一致。
  比如我用的是Poco C++框架,处理过程如下:

response.setChunkedTransferEncoding(true);
response.setContentType("application/json");
std::ostream &ostr = response.send();
try
{   				
	MyPartHandler partHandler;
	HTMLForm form(request, request.stream(), partHandler);

	std::ofstream outfile;
	outfile.open("Image/1.jpg", std::ios::binary | std::ios::out | std::ios::trunc);
	outfile.write(&partHandler.buffer()[0],partHandler.length());
	outfile.close();
	
	returnMsg.set("msg"," "+partHandler.fileName()+" have been received successfully");	
	std::string temp= Poco::Dynamic::Var(returnMsg).toString();
	ostr<<temp;
}
catch(const Poco::Exception& e) 
{	
	app.logger().log(e,__FILE__,__LINE__);
}
//自己的处理类,用来获取HTMLForm里面的信息
class MyPartHandler: public Poco::Net::PartHandler
{
public:
	MyPartHandler():
		_length(0)
	{
	}
	
	void handlePart(const MessageHeader& header, std::istream& stream)
	{
		_type = header.get("Content-Type", "(unspecified)");
		if (header.has("Content-Disposition"))
		{
			std::string disp;
			NameValueCollection params;
			MessageHeader::splitParameters(header["Content-Disposition"], disp, params);
			_name = params.get("name", "(unnamed)");//获取网页给文件对应的key名
			_fileName = params.get("filename", "(unnamed)");//获取上传的文件名
		}
		StreamCopier::copyToString(stream, _buffer);//二进制数据写入到buffer
		_length=_buffer.size();	//获取二进制数据长度
	}
}

  实际上,二进制的数据永远只是数据,具体还要看你把这些数据保存为什么文件,服务器后端收到的就是什么格式的文件。

二、浏览器下载图片

1.后端

  后端对应传输图片给前端,只要注意两件事:
第一,response的ContentType一定是image/jpeg或者image下面的其它文件类型。
第二,返回的文件数据一定要完整,这个可以通过对比浏览器收到的数据的Content-Length和文件本身的大小来判断,是否是后端没有传输完文件。
  Poco代码如下:

response.setContentType("image/jpeg");
std::ifstream infile;
infile.open("Image/1.jpg", std::ios::binary | std::ios::in | std::ios::ate);
long int length;  
length = infile.tellg();           //读取文件长度 
infile.seekg(0, std::ios::beg);    //返回文件首部
char *buffer = new char[length];    
infile.read(buffer, length);       // 读取文件二进制数据到buffer中
response.sendBuffer(buffer, length);//直接发送指定长度的buffer

2.前端

  对于前端数据,最简单的是使用下面代码来显示:

<img src="http://你的网址的接口" >

  但是如果后端对应的接口的http的request的method不是GET就不能使用这个方法,或者如果需要获取response里面自定义的属性或者其它的数据就不能使用< img >标签。应该直接接受二进制数据:

var url = "你的网址的接口";
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "blob";
xhr.onload = function() {
	if (this.status == 200) {
		var blob = this.response;
		console.log(this);
		console.log(blob);
		var img = document.createElement("img");
		img.onload = function(e) {
			window.URL.revokeObjectURL(img.src); 
		};
		img.src = window.URL.createObjectURL(blob);
		$("#imgcontainer").html(img);    
	}
}
xhr.send();

这样子返回就可以是二进制的数据,取决于前端想把数据保存为什么样子,然后也可以获取response里面的属性。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值