在写新博客的时候,遇到需要用户上传自定义图片的处理,查了一番资料,决定用cropper和pillow来处理需要剪裁的图片上传,大致思路是:前端收集用户上传的图片和用户剪裁的尺寸数据,后台接收图片后按数据进行剪裁保存,但是剪裁的临时文件我还没有想出一个比较合理的办法,这里只记录前期的简单实现
一.cropper
github: https://github.com/fengyuanchen/cropper
这里我按教程引入了
cropper.min.css
cropper.min.js
但是会报错,TypeError: image.cropper is not a function直到我引入了这个解决了报错问题,此外他们都是依赖jquery的
jquery-cropper.min.js
{#cropper编辑区域#} <div class="avatar-wrapper" id='avatar-wrapper'> <img src=""> </div> {#头像预览区域#} <div class="avatar-preview" style=" border-radius: 15%">
<img style="width: 96px; height: 96px;" src="">
</div> {#上传按钮#} <a id="upload" class="btn btn-primary">上传头像</a> <label class="btn btn-primary" for="avatar-input">选择图片</label>
{#form#}
<form action="" method="post" id="avatar_form" enctype="multipart/form-data">
{%csrf_token%}
<input style="display:none" type="file" class="avatar-input" id="avatar-input" name="avatar_file" accept=".jpg,.jpeg,.png">
<input type="hidden" id="avatar_x" name="avatar_x">
<input type="hidden" id="avatar_y" name="avatar_y">
<input type="hidden" id="avatar_width" name="avatar_width">
<input type="hidden" id="avatar_height" name="avatar_height">
</form>
模板的主要内容就是这些,主要是编辑区域、预览区域、上传按钮和隐藏的form组成,其中预览区域可以根据自己的需求先展示原头像或者默认头像,通过js将图片和尺寸数据保存在隐藏的form中上传到后台
cropper的初始化:
var image = $('#avatar-wrapper img'); image.cropper({ checkImageOrigin: true, //检查图片来源 dragMode: 'move', //图片可移动 restore:false, //窗体调整大小之后不自动恢复裁剪区域 zoomOnWheel: false, //不允许通过鼠标滚轮缩放 zoomOnTouch: false, //不允许通过触摸缩放 aspectRatio: 1 / 1, //裁剪比例 autoCropArea: 0.5, //裁剪背景透明度 autoCropArea: 1, //自动裁剪的比例 preview: ".avatar-preview",//预览区域 crop: function (e) { //返回图片编辑相关数据 $('#avatar_x').val(e.detail.x); $('#avatar_y').val(e.detail.y); $('#avatar_width').val(e.detail.width); $('#avatar_height').val(e.detail.height); }, });
图片上传到cropper进行剪裁:
$("#avatar-input").change(function(){ var URL = window.URL || window.webkitURL; if(URL){ var files = this.files; if (files && files.length){ var file = files[0]; if (/^image\/\w+$/.test(file.type)) { var blobURL = URL.createObjectURL(file); image.cropper('reset').cropper('replace', blobURL); $('.avatar_crop .disabled').removeClass('disabled'); } else { alert('请选择一张图片'); } } } });
上传到后台:(我使用的jquery-form.js插件,普通的ajax方法也可以)
$('#upload').click(function () { if($('#avatar-wrapper img').attr('src')==''){ $('#infoModal h4').html('请先选择一个图片') $('#infoModal').modal('show') return false;} var $form=$("#avatar_form") $form.ajaxSubmit(function (headpicaddress) { })
二.pillow
def user_my_info_headpic(request): # 剪裁数据获取 top = int(float(request.POST['avatar_y'])) buttom = top + int(float(request.POST['avatar_height'])) left = int(float(request.POST['avatar_x'])) right = left + int(float(request.POST['avatar_width'])) # 图片临时保存 with open(os.path.join(settings.BASE_DIR, "test1.jpg"), "wb") as f: for line in request.FILES['avatar_file']: f.write(line) # 打开图片 im = Image.open(os.path.join(settings.BASE_DIR, "test1.jpg")) # 剪裁图片 crop_im = im.crop((left, top, right, buttom)) # 保存图片 crop_im.save(os.path.join(settings.BASE_DIR, "test2.jpg")) return HttpResponse("ok")
这是我的view方法,路由部分省略了,只是简单的保存在一个临时位置,后面我会整理出一个更合理的方法和完整的流程