是一种用64个字符来表示任意二进制数据的方法,完成了数据在HTTP协议上的传输
它是一种编码方式,而非加密方式
数据编码之后,数据量会变大,变大1/3左右
base64参考:https://www.zhihu.com/question/36306744
简单说,因为某些场合并不能传输或者储存二进制流。
比如,如果一个传输协议是基于ASCII文本的,那么它就不能传输二进制流,那你要将二进制流传输就得编码。常见的诸如 http 协议的 url 就是纯文本的,不能直接放二进制流。
特别的,大多数现代语言的 String 类型,都不能直接储存二进制流,但可以储存BASE64编码的字符串。如果你希望用 String 类型操作一切数据,那就没法直接用二进制流。
当然,另外还有一个原因,就是某些协议会对二进制流中的特定字符进行特殊处理(比如ASCII的0~32编码的字符在某些传输介质中,是会被当作特殊含义处理的),这种时候就需要通过编码来避开这些特定字符了。
所以一般图片小于10kb的时候,才用base64图片
(1)base64格式的文本内容较多,存储在数据库中增大了数据库服务器的压力;
(2)网页加载图片虽然不用访问服务器了,但因为base64格式的内容太多,所以加载网页的速度会降低,可能会影响用户的体验。
(3)base64无法缓存,要缓存只能缓存包含base64的文件,比如js或者css,这比直接缓存图片要差很多,而且一般HTML改动比较频繁,所以等同于得不到缓存效益。
a-z A-Z 0-9 和 +
/
组成base64
首先将待编码的内容转换成8位二进制,每3个字符为一组
如果编码前的长度是
3n+1,编码后的内容最后面补上2个 =,如果编码前的长度是3n+2,内容最后面补上1个 =。3的倍数则不用
再将每一组的二进制内容拆分成
6位的二进制,不足6位的后面补足0
每个6进制的数字前面补足
0,保证变成8位二进制
将补足后的内容根据base64编码表转换成base64内容输出
(不足四个字符的时候会用 =来补足,下面会说明)
编码前 “hb”
1.根据ascii码转换成8位二进制,3个为一组:
01101000,01100010
2.编码前长度是3n+2,所以后面补1个 ‘=’:
01101000,01100010,=
3.拆分成6位二进制,不足6位的在后面补足0,0010补足变成001000:
011010,000110,001000,=
4.每个6进制的数字前面补足0:
0011010,00000110,00000010,=
5.根据base64编码表输出:
aGI=
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.springframework.util.Base64Utils;
public class Base64Test {
public static void main(String[] args) {
byte[] encode = Base64Utils.encode("abc".getBytes(StandardCharsets.UTF_8));
System.out.println(new String(encode));
byte[] decode = Base64Utils.decode(encode);
System.out.println(new String(decode));
// 获取编码器
Base64.Encoder encoder = Base64.getEncoder();
byte[] encode = encoder.encode("abc".getBytes());
System.out.println(new String(encode));
// 获取解码器
Base64.Decoder decoder = Base64.getDecoder();
byte[] decode = decoder.decode(encode);
System.out.println(new String(decode));
// 或者使用
byte[] encode2 = Base64Utils.encode("abc".getBytes());
}
}
<img src = "data:image/png;base64,base64代码">
一般用在比特币里面的一种编码方式,没有数字0,O(大写字母 O)、I(大写字母i)、l(小写字母L),+,/
编码流程
将ascii编码的字符串(256进制),转换成58进制。然后按照58进制的码表转换成相应的字符。
1、将字符串的每个字节换算成ASCII(0-255) (字符串实际上就是256进制的数字组合):
源字符串为:ABD
换算后: 65 66 68
2、将256进制的数字转换成10进制数字:
256进制数:65 66 68
转成10进制:(65 * 256 + 66) * 256 + 68 = 4276804
3、将10进制数字转换成58进制数字:
10进制数:4276804
58进制数: 21 53 20 0
4、将58进制数字的每一位按照表格转换成对应的字符:
58进制数:21 53 20 0
码表:123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ
转换后的字符:nVm1
【注】任意进制之间的转换,先将数字转10进制再转其它进制
解码流程
按码表把字符转成58进制数字,再转256进制,按ascii把256进制数字转字符。
1、字符串每一位按码表替换成数字(58进制):
源字符: nVm1
58进制数:21 53 20 0
2、58进制转10进制:
58进制数:21 53 20 0
10进制数:4276804
3、10进制转256进制:
10进制数:4276804
256进制: 65 66 68
4、256进制转字符(按ascii转)
256进制: 65 66 68
字符:ABD
【注】任意进制之间的转换,先将数字转10进制再转其它进制
具体细节可自行添加
@GetMapping("/getPic")
public ResponseEntity<byte[]> getPic(HttpServletResponse httpServletResponse) throws Exception {
FileInputStream fileInputStream = new FileInputStream(new File("D:\\Picture\\Appearance 1.png"));
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<>(IOUtils.toByteArray(fileInputStream), headers, HttpStatus.OK);
}
浏览器输入地址,然后浏览器就会显示图片了
具体细节可自行添加
@GetMapping({"/captchaImage"})
public ResponseMessage<Map<String, Object>> getCaptchaImage() throws Exception {
HashMap retMap = new HashMap();
String text = CaptchaHelper.generateVerifyCode(4);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 生成验证码图片, 具体可参考百度
CaptchaHelper.outputImage(111, 36, outputStream, text);
retMap.put("img", "data:image/gif;base64," + Base64.getEncoder().encodeToString(outputStream.toByteArray()));
return ResponseMessage.success("success!", retMap);
}
具体细节可自行添加
@GetMapping("/getPic2")
public ResponseEntity<Resource> getPic2() throws Exception {
String contentDisposition = ContentDisposition
.builder("attachment")
.filename("pic.png")
.build().toString();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
.contentType(MediaType.IMAGE_PNG)
.body(new FileSystemResource("D:\\Picture\\Appearance 1.png"));
}