最近使用人脸识别restfulAPI遇到了要求图片base64编码后传输问题。
借此机会了解下什么是base64编码。
部分内容参考自阮一峰blog:
/blog//06/base64.html
1 什么是base64编码
所谓Base64,就是说选出64个字符----小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是65个字符)----作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。
2 解决的问题
网络传送渠道(纯文本协议)并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送。
http针对二进制数据做了特殊规定是可以支持传输二进制数据的,但如果在json内部传输二进制数据就会遇到这种问题,我们可以先进行base64编码转成字符串进行处理。
3 主要用途
证书 电子邮件数据,经常要用到Base64编码。
4 如何编码
第一步,将每三个字节作为一组,一共是24个二进制位。
第二步,将这24个二进制位分为四组,每个组有6个二进制位。
第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。
第四部, 每个字节的对应符号即为base64编码后的值。
Base64编码后的文本,会比原文本大出三分之一左右。
5 代码实现
nodejs实现:
var base64str1 = new Buffer(bitmap).toString('base64');
C++实现:
以下代码来自百度云SDK中base64编码部分。简单好用。
Bash64.h:
#ifndef __BASE64_H__#define __BASE64_H__#include <iostream>#include <string>static const std::string base64_chars ="ABCDEFGHIJKLMNOPQRSTUVWXYZ""abcdefghijklmnopqrstuvwxyz""0123456789+/";static inline bool is_base64(const char c){return (isalnum(c) || (c == '+') || (c == '/'));}std::string base64_encode(const char * bytes_to_encode, unsigned int in_len){std::string ret;int i = 0;int j = 0;unsigned char char_array_3[3];unsigned char char_array_4[4];while (in_len--){char_array_3[i++] = *(bytes_to_encode++);if(i == 3){char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);char_array_4[3] = char_array_3[2] & 0x3f;for(i = 0; (i <4) ; i++){ret += base64_chars[char_array_4[i]];}i = 0;}}if(i){for(j = i; j < 3; j++){char_array_3[j] = '\0';}char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);char_array_4[3] = char_array_3[2] & 0x3f;for(j = 0; (j < i + 1); j++){ret += base64_chars[char_array_4[j]];}while((i++ < 3)){ret += '=';}}return ret;}std::string base64_decode(std::string const & encoded_string){int in_len = (int) encoded_string.size();int i = 0;int j = 0;int in_ = 0;unsigned char char_array_4[4], char_array_3[3];std::string ret;while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {char_array_4[i++] = encoded_string[in_]; in_++;if (i ==4) {for (i = 0; i <4; i++)char_array_4[i] = base64_chars.find(char_array_4[i]);char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];for (i = 0; (i < 3); i++)ret += char_array_3[i];i = 0;}}if (i) {for (j = i; j <4; j++)char_array_4[j] = 0;for (j = 0; j <4; j++)char_array_4[j] = base64_chars.find(char_array_4[j]);char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; } return ret; }#endif
Test_main.cpp:
#include <string>#include <iostream>#include "base64.h"#include <fstream>#include <stdlib.h>using namespace std;int main(int argc, char** argv){fstream f, f2;f.open("test.jpg", ios::in|ios::binary);f.seekg(0, std::ios_base::end);std::streampos sp = f.tellg();int size = sp;cout << size << endl;char* buffer = (char*)malloc(sizeof(char)*size);f.seekg(0, std::ios_base::beg);//把文件指针移到到文件头位置f.read(buffer,size);cout << "file size:" << size << endl;string imgBase64 = base64_encode(buffer, size);cout << "img base64 encode size:" << imgBase64.size() << endl; string imgdecode64 = base64_decode(imgBase64);cout << "img decode size:" << imgdecode64.size() << endl;f2.open("out.jpg", ios::out|ios::binary);f2 << imgdecode64;f2.close();return 0;}
编译:
g++ -D_LINUX -I. -std=c++11 ./test_main.cpp -o sample_X86_64
输出:
file size:23615img base64 encode size:31488img decode size:23615
源码
链接: /s/1MLJVytHqqIzurR31Y0dytw 提取码: i9h3
百度盘中的代码中test_main.cpp 请替换为文中代码。