前言:
主要是来源于一个需求,我需要将页面生成pdf然后下载,鉴于此页面的特殊性,最后决定的方案是我对后端难以生成的部分进行html截图上传到后端,然后后端将图片以及一些其它的部分根据itext生成pdf,然后返回给我。页面的实现效果是我点击按钮,然后pdf被下载。
参考:
第一章 在前端截图下载
值得注意的是html2canvas要用document.querySelector()来获取元素,如果使用$("#xxx")或者document.getElementById()我这里会提示Element is not attached to a Document(后面再次测试时发现只是$("#xxx")不行,document.getElementById()又可以了)
function downloadStudentData(){
console.log("下载学生数据")
//打印雷达图
html2canvas(document.querySelector("#screenDiv"),{
width: 1000,
height:1000,
}).then(canvas => {
document.body.appendChild(canvas)
var dataUrl = canvas.toDataURL("image/png");
console.log(dataUrl);
let aLink = document.createElement('a');
//取出图片中的base64数据
var bstr = atob(dataUrl.split(',')[1])
var n = bstr.length
var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
var blob = new Blob([u8arr])
let evt = document.createEvent("HTMLEvents");
evt.initEvent("click", true, true);//initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为
aLink.download = "test.png";
aLink.href = URL.createObjectURL(blob);
aLink.click()
});
}
第二章 将截图传至后端并下载文件
当然图片前端下载就好,这里本人要上传到后端主要是想测试下图片在后端能不能用。
之前想的是用ajax上传并下载文件,但是试了一下发现ajax不能下载文件,从网上找了个不严谨的说法:浏览器中js不能操作磁盘,不然会引起安全问题,要想操作磁盘需要调用浏览器的一些其它的api。
这里采用的是模拟表单提交,值得注意的是,在后端转化图片时要把base64图片的图片头去掉即把data:image/png;base64,去掉,只保留base64图片的数据。
前端:
function downloadStudentData(){
//打印雷达图
html2canvas(document.querySelector("#screenDiv"),{
width: 1000,
height:1000,
}).then(canvas => {
// document.body.appendChild(canvas)
var dataUrl = canvas.toDataURL("image/png");
var form = $("<form></form>").attr("action", url).attr("method", "post");
form.append($("<input></input>").attr("type", "hidden").attr("name", "canvasPhotoBase64Data").attr("value", dataUrl));
form.appendTo('body').submit().remove();
});
}
后端:
@RequestMapping("/test")
@RestController
public class TestUpload {
@RequestMapping("/testUploadPhoto")
public void testUploadPhoto(String canvasPhotoBase64Data, HttpServletResponse response){
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
System.out.println("begin");
System.out.println(canvasPhotoBase64Data);
BASE64Decoder decoder = new BASE64Decoder();
try {
FileOutputStream write = new FileOutputStream(new File("testPhoto"));
byte[] decoderBytes = decoder.decodeBuffer(canvasPhotoBase64Data.split(",")[1]);
response.setHeader("content-disposition", "attachment;filename=" + "test.png");
response.setContentType("multipart/form-data");
response.getOutputStream().write((decoderBytes));
response.getOutputStream().flush();
response.getOutputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}