一、问题复现
环境是vue2 + python + django + nginx + uwsgi的线上服务环境。
最近在项目中发现一个关于html2canvas的问题,生成图片的时候莫名的出现跨域问题。就是页面有其他图片的时候,生成图片会报跨域问题,如下图:
注意:页面图片是直接从访问的django的静态文件夹下的图片的。如:http://xxxx/static/xxx.png
这包括已经给django添加了白名单,在django导入了中间件等操作,线下环境测试是正常的,线上生产环境就会出问题,使用了网上普遍的办法如下,都没有生效。
二、常见的解决方式一
在html2canvas添加useCORS的方式,并且在img标签中添加**crossorigin=“anonymous”**如下:
html2canvas(document.querySelector("#capture"), {useCORS: true}).then(canvas => {
...
});
<img :src="'http://xxxx/xxxx/xxx.png&time=' + new Date().getTime()" crossorigin="anonymous" alt=""/>
上面标签中拼接了一个new Date().getTime(),这是为了防止浏览器缓存,每次都是重新拿图片,后面接了一个**crossorigin=“anonymous”**这个属性会导致图片拿不到,但是我这里会继续报跨域问题。
三、常见的解决方式二:
基于上面添加useCORS的配置,通过Nginx模块Http_Headers_Module来添加Access-Control-Allow-Origin允许的地址。
add_header Access-Control-Allow-Origin * # 这里的*是所有地址都可以去访问,线上环境建议写自己的地址
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
这些配置完成后,依然报跨域错误。
四、解决方案
在django中添加应用,单独写一个接口,通过django的HttpResponse方法去返回图片。
创建一个新的应用,这里就用命令去创建了,手动添加的记得注册一下这个应用。
# 项目根目录去执行
python manage.py startapp img
# urls文件中
from django.urls import path
from img.views import Img
urlpatterns = [
path('img', Imag.as_view()),
]
# view文件中
import os
from django.conf import settings
from django.http import HttpResponse
from django.views import View
class Img(View):
def get(self, request):
try:
# 这里获取的值为xxx.png
img_path = request.GET.get('path', '')
# 拼接完整的路径
img_path = path.join(settings.STATIC_ROOT, "/" + img_path)
# 判断文件是否存在
if os.path.exists(img_path):
with open(imagepath, 'rb') as f:
img_data = f.read()
return HttpResponse(image_data, content_type="image/png")
else:
# 文件不存在的时候根据自己项目需求去写, 这里就不再写了
pass
except Exception as e:
# 异常处理我这里就简写了
print(str(e))
前端访问地址:http://项目地址/img?path=xxx.png
至此就前端就可以正常使用html2canvas截图了。