使用html2canvas时图片跨域问题的解决方法

html2canvas 是一个可以将整个 html 转为一张图片的 JS 插件,但是,我们在使用过程中,难免会遇到图片跨域的问题,这个问题也同样困扰了我好久,但最终还是找到了解决办法,现在就来分享给大家。

解决思路(将图片转为 base64)

什么是 base64?
简单来说就是一串二进制数据。详细了解,请 Google。
为什么要转成 base64
普通 src 存在跨域问题,而 base64 已经将图片进行编码,相当于下载到了本地,因此不会存在跨域.

解决方法

客户端: 废话不多说,直接上代码

1
2
3
4
5
6
7
8
9
10
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
var dataURL = canvas.toDataURL("image/" + ext);
return dataURL;
}

由于 JS 将图片转为 base64 兼容性不太好,所以有很多时候还是会出问题的。
Don’t worry! 接下来还有服务器端的转换

服务器端: 这里只有 base64 转换的 JAVA 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.io.IOException;
import java.nio.file.*;
import java.util.Base64;

import static java.lang.System.out;

public class Base64Trans {

/**
* 从图片文件中读取内容。
* @param path 图片文件的路径。
* @return 二进制图片内容的byte数组。
*
*/
private byte[] readFile(Path path) {
byte[] imageContents = null;

try {
imageContents = Files.readAllBytes(path);
} catch (IOException e) {
out.println("读取文件出错了...~zZ");
}

return imageContents;
}

/**
* 编码图片文件,编码内容输出为{@code String}格式。
* @param imageContents 二进制图片内容的byte数组。
* @return {@code String}格式的编码内容。
*/
private String base64Encoding(byte[] imageContents) {
if(imageContents != null)
return Base64.getEncoder().encodeToString(imageContents);
else return null;
}

/**
* 解码图片文件。
* @param imageContents 待解码的图片文件的字符串格式。
* @return 解码后图片文件的二进制内容。
*/
private byte[] base64Decoding(String imageContents) {
if(imageContents != null)
return Base64.getDecoder().decode(imageContents);
else return null;
}

/**
* 将解码后的二进制内容写入文件中。
* @param path 写入的路径。
* @param imageContents 解码后的二进制内容。
*/
private void writeFile(Path path, byte[] imageContents) {
if(imageContents != null) {
try {
Files.write(path, imageContents, StandardOpenOption.CREATE);
} catch (IOException e) {
out.println("写入文件出错了...~zZ");
}
}
}

public static void main(String[] args) {
Base64Trans bt = new Base64Trans();
String url = "http://static.ruitaowang.com/qr/qr_1_83.png";
String encodingString = bt.base64Encoding(bt.readFile(Paths.get(url)));

out.println("二进制图片文件Base64码:" + encodingString);

// bt.writeFile(Paths.get("D:/temp/mm2.png"), bt.base64Decoding(encodingString));
// out.println("任务结束...");
}
}