一、前言
背景:最近有一个需求,要根据html页面,生成一个图片,并发送邮件。
后端架构:Python+Django。
技术选择:imgkit+wkhtmltoimage组合生成图片
前提条件:安装wkhtmltopdf
二、代码实现
- 首先是制作一个html模板文件:
- 后端功能实现
wkhtmltoimage的位置:在安装的wkhtmltopdf应用文件夹的bin文件夹下,
wkhtmltopdf\bin\wkhtmltoimage.exe
EXPORT_FILE
:模板文件路径常量,EXPORT_FILE = os.path.join(BASE_DIR, 'xx/export_file.html')
@csrf_exempt
def export_img(request):
try:
content = request.POST.get("content")
html_string = format_export_string(content)
img_name = "日报-" + now_time() + ".png"
if settings.DEBUG:
config = imgkit.config(wkhtmltoimage=r'E:\wkhtmltopdf\bin\wkhtmltoimage.exe')
else:
config = imgkit.config(wkhtmltoimage='/usr/local/bin/wkhtmltoimage')
img_file = imgkit.from_string(html_string, False, config=config)
return download_file(img_file, img_name)
except Exception as e:
print(e)
logger.error(e)
return JsonResponse({"result": False, "message": str(e)})
def format_export_string(content):
export_file = open(EXPORT_FILE, encoding='utf-8')
file_content = export_file.read()
export_file.close()
html_content = content.replace("&", "&").replace(">", ">") \
.replace('"', '"') \
.replace("'", r"'") \
.replace("<", "<") \
.replace(" ", " ") \
.replace("\n", '') \
.replace("\r", "").strip()
return str(file_content).replace('{body_content}', html_content)
def download_file(file_buffer, file_name):
response = HttpResponse(file_buffer, content_type='APPLICATION/OCTET-STREAM')
# response['Content-Disposition'] = 'attachment; filename' + urlquote(file_name)
response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(file_name))
response['Content-Length'] = len(file_buffer)
return response
- 前端方法实现
注意:前端页面所有css都要自己手写,不要使用比如element或iview等vue组件,会出现问题。除此之外,如果有echarts图表,请使用svg的渲染方式。
说明:该方法可以在前端导出图片
exportImg() {
const VueEnv = process.env.NODE_ENV
const ApiUrl = VueEnv === 'production' ? window.siteUrl : 'http://127.0.0.1:8070/'
const eleForm = document.createElement('form')
eleForm.id = 'eleForm'
eleForm.method = 'post'
eleForm.action = ApiUrl + 'report/export_img'
eleForm.target = '导出'
const eleInput = document.createElement('input')
eleInput.type = 'hidden'
eleInput.name = 'content'
eleInput.value = document.getElementById('day-report').innerHTML
eleForm.appendChild(eleInput)
eleForm.addEventListener('onsubmit', function() {
this.$CwMessage('success', '导出图片')
})
document.body.appendChild(eleForm)
eleForm.submit()
document.body.removeChild(eleForm)
}