新手问题 问一下有没有上传之前就进行裁减好图片的'gem'啊,我现在用的 paperclip,每次都要先上传,才能进行图片的裁减,感觉特别不方便

tianlitao · 2014年10月27日 · 最后由 tianlitao 回复于 2014年10月29日 · 4023 次阅读

有没有知道的,或者用什么方法可以实现在上传之前进行裁减的,裁减完成之后在进行上传服务器

得找 js 库。

有一种方法,就是把图片和裁剪参数一起上传,那么就要实现,在浏览器端能够直接打开图片。有这么一个库帮你做好了底层的工作,moxie

其中有两个关键的对象:mOxie.ImagemOxie.FileInput

mOxie.FileInput 可以让你绑定一个按钮,然后打开文件选择框,然后得到文件,然后再用 mOxie.Image 来加载并显示到页面中。

以下是一部分代码,包含了表单的提交,对于裁剪预览的插件使用的是 jquery.cropper

var $browseButton   = $("#fire-photo-modal")
  , $imageInput     = $("#image-input")
  , $imagePreview   = $("#image-preview")
  , $imageCropModal = $("#upload-client-photo-modal")
  , $uploadLogoForm = $("#upload-logo-form")
  , geometryParam   = "200x200+0+0"

mOxie.Env.swf_url = "/files/Moxie.swf";

var preloader = new mOxie.Image()
  , currentId = null;

// 显示图片,并初始化裁图程序
preloader.onload = function() {
  var $image = $(new Image());

  $image.data("originWidth", preloader.width);
  $image.data("originHeight", preloader.height);
  $image.attr("src", preloader.getAsDataURL("image/png"));
  $image.attr("id", "image-id-" + currentId);

  $image.load();

  $imagePreview.html($image);

  $image.cropper({
    aspectRatio: 9/9,
    minWidth: 100, minHeight: 100,
    data: { x: 0, y: 0, width: 200, height: 200 },
    preview: "#image-crop-preview",
    done: function(data) { geometryParam = data.width + "x" + data.height + "+" + data.x + "+" + data.y; }
  });
}

var fileInput = new mOxie.FileInput({
  runtime_order: 'html5,flash,silverlight,html4',
  browse_button: "fire-photo-modal",
  accept: [{title: "图片", extensions: "jpg,gif,png"}]
})

fileInput.onchange = function(e) {
  var file = e.target.files[0];

  if (!file) {
    return false;
  } else if (file.size > 1048576) { // 图片不能大于1MB
    alert("请选择小于1MB的图片(jpg,gif,png)");
    file.destroy();
    return false;
  }

  if (currentId) {
    var $image = $("#image-id-" + currentId);
    $image.cropper("destroy");
    $image.remove();
  }

  currentId = file.uid;
  preloader.load(file);           // 加载选择的图片文件
  $imageCropModal.modal('show');  // 显示裁剪图片的弹出框
}

fileInput.init();

$("#crop-modal-return-btn").on("click", function(e){ $imageCropModal.modal("hide"); });
$("#crop-modal-submit-btn").on('click', function(e){
  var $this = $(e.target)

  if ($this.attr("disabled")) {
    return false;
  } else {
    $this.html("保存中");
    $this.attr("disabled", "disabled");
  }

  var xhr = new mOxie.XMLHttpRequest()
    , formData = new mOxie.FormData()
    , params = $uploadLogoForm.serializeArray()

 //  将图片和裁剪参数一并提交
  formData.append("client[image_url]", preloader.getAsBlob("image/png"));
  formData.append("client[crop_geometry]", geometryParam);

  for (var i=0; i<params.length; i++) {
    formData.append(params[i].name, params[i].value);
  }

  xhr.open($uploadLogoForm.attr("method"), $uploadLogoForm.attr("action"));
  xhr.responseType = "json";
  xhr.onload = function() {
    $this.html("保存");
    $this.removeAttr("disabled");
    if (xhr.status == 200) {
      $fillClientProfileForm.find("[name='logo']").val("pass");
      $browseButton.css("background", "url(" + xhr.response["image_url"] + ") 0 0 / 120px 120px no-repeat");
      $browseButton.html('');
      $imageCropModal.modal('hide');
    } else if (xhr.status == 400) {
      alert("服务器发生错误,...");
      console.dir(xhr.response);
    } else {
      alert("服务器发生错误,...")
      console.dir(xhr.response);
    }
  }
  xhr.send(formData);
});

这个库需要花点心思和时间看看文档,其文档不是很详细,所以需要去看看别人的例子和不断地试错。 另外还需要看看这个库 Plupload

#2 楼 @hz_qiuyuanxin html4 也能实现本地图片读取?没看到 moxie 哪里有实现~

#3 楼 @small_fish__ 源码我没去看,这个不太清楚。

理论上上传到服务器之前,是 js 的事,但是因为安全关系,js 一般不能处理文件。 不知道用 flash 能不能做这样的功能。

不同的浏览器,对读取本地图片的方式不一样

html5 可以读取,但是 html5 又不是所有浏览器都支持

谢谢大家的热心回答,了解了下 moxie,由于时间的关系没有使用,后来使用了@aptx4869 提供的 js,可能是新手的原因,很多地方弄不很清楚,弄了两天也没有达到需求,由于时间关系今天不得已放弃这个了想法,又回到的继续先上传在处理的方式,如果最近能有时间会继续回头做做这块,再次谢谢大家

需要 登录 后方可回复, 如果你还没有账号请 注册新账号