web-dev-qa-db-ja.com

Dropzone.js +クライアント側の画像のサイズ変更

統合したいDropzone.jsクライアント側の画像のサイズ変更。サムネイルのサイズを変更する機能があることは知っていますが、アップロード前に主画像のサイズを変更する機能を作りたいのですが。誰か私を助けてくれませんか?

16
Pedro Canelas

アップロード前のサイズ変更機能に関するDropzoneのドキュメントはわかりにくいです。読み方では、幅を制限するか、高さを制限するか、両方を制限してアスペクト比を犠牲にして画像を歪めることができます。これはそうではありません。この:

resizeWidth: 1000, resizeHeight: 1000,
resizeMethod: 'contain', resizeQuality: 1.0,

幅または高さのいずれかを最大1000pxのいずれか大きい方に制限します。もう一方は、画像を歪めることなく、アスペクト比に従って縮小されます。たとえば、私のテストでは、2688x1512の画像をアップロードしました。 Dropzoneは、サムネイルをトリミングしてデフォルトの120x120にサイズ変更しましたが、サーバーに送信されたファイルは、Dropzoneによって1000x562に個別にサイズ変更されてから、サーバーに送信されました。

ここには興味深い警告があります。 JPEGは再圧縮されて不可逆になるため、resizeQualityを1.0にしても失われます。この機能はめちゃくちゃ大きなファイルを防ぐ方法と考えていますが、回避できる場合は(サーバーで1回、クライアントで1回)、サイズを2度変更するように注意してください。

これで十分ではなく、変換メソッドをオーバーロードしたい場合は、createThumbnailコードパスがアップロードごとに2回使用され、1回は次のようなサムネイルを作成するため、Dropzone内のコードパスをたどるのは少し混乱します。サーバーに渡す前に、ここで画像のサイズを事前に変更する必要があります。同様に、resizeメソッドの名前は紛らわしいものです。 resizeWidth etcはアップロード用に画像を準備することを示し、 resize はサムネイルのサイズ変更を示し、サーバーに送信される画像には何もしません。

13
Chris Moschini

addedfileからファイルをアップロードせずにそれを行う方法は次のとおりです。

重要なことは、autoQueueオプションをfalseに設定することです。これにより、dropzoneはユーザーが選択したファイルを自動アップロードしません。

var dropzone = new Dropzone (".dropzone", {
  ...
  autoQueue: false,
  ...
});

次のステップは、addedfileイベントでサイズ変更およびサイズ変更されたバージョンをエンキューすることです。

dropzone.on("addedfile", function(origFile) {
  var MAX_WIDTH  = 800;
  var MAX_HEIGHT = 600;

  var reader = new FileReader();

  // Convert file to img

  reader.addEventListener("load", function(event) {

    var origImg = new Image();
    origImg.src = event.target.result;

    origImg.addEventListener("load", function(event) {

      var width  = event.target.width;
      var height = event.target.height;


      // Don't resize if it's small enough

      if (width <= MAX_WIDTH && height <= MAX_HEIGHT) {
        dropzone.enqueueFile(origFile);
        return;
      }


      // Calc new dims otherwise

      if (width > height) {
        if (width > MAX_WIDTH) {
          height *= MAX_WIDTH / width;
          width = MAX_WIDTH;
        }
      } else {
        if (height > MAX_HEIGHT) {
          width *= MAX_HEIGHT / height;
          height = MAX_HEIGHT;
        }
      }


      // Resize

      var canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;

      var ctx = canvas.getContext("2d");
      ctx.drawImage(origImg, 0, 0, width, height);

      var resizedFile = base64ToFile(canvas.toDataURL(), origFile);


      // Replace original with resized

      var origFileIndex = dropzone.files.indexOf(origFile);
      dropzone.files[origFileIndex] = resizedFile;


      // Enqueue added file manually making it available for
      // further processing by dropzone

      dropzone.enqueueFile(resizedFile);
    });
  });

  reader.readAsDataURL(origFile);
});

dataURLdropzoneファイルに変換する関数を次に示します。サイズ変更されたファイルのコンテンツを取得するために canvas.toDataURL() の代わりに canvas.toBlob() を使用する場合、プロセスはより単純になる可能性がありますが、後者はサポートされていませんすべてのブラウザ。

this 関数の修正バージョンです。

function base64ToFile(dataURI, origFile) {
  var byteString, mimestring;

  if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
    byteString = atob(dataURI.split(',')[1]);
  } else {
    byteString = decodeURI(dataURI.split(',')[1]);
  }

  mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0];

  var content = new Array();
  for (var i = 0; i < byteString.length; i++) {
    content[i] = byteString.charCodeAt(i);
  }

  var newFile = new File(
    [new Uint8Array(content)], origFile.name, {type: mimestring}
  );


  // Copy props set by the dropzone in the original file

  var origProps = [ 
    "upload", "status", "previewElement", "previewTemplate", "accepted" 
  ];

  $.each(origProps, function(i, p) {
    newFile[p] = origFile[p];
  });

  return newFile;
}
12
rodic

Dropzoneバージョン5が最近リリースされたため、dropzone 5にアップグレードする場合は、resizeWidthおよびresizeHeighを使用して、クライアント側でイメージを圧縮できます。

そのうちの1つだけを指定した場合、dropzoneは元のアスペクト比を尊重します。たとえば、オプションresizeWidth: 800を追加しただけの場合、画像はwidth=800ピクセルに圧縮され、元の画像のアスペクト比になります。尊重されます。

6
Hooman Bahreini

これは、Dropzone.jsによって行われるアップロードをバイパスすることで実行できます。そのためには、オプションでautoQueue: falseを設定する必要があります( Bootstrapの例 のように)。

次に、サムネイルを送信するか、難しい方法で送信します。


解決策1:サムネイルを送信する

myDropzone.on('thumbnail', function(file, dataURL) {
   $.post('http://example.com', {img: imgToSend})
})

オプションにサイズ変更機能を追加することで、サイズ変更/トリミングする方法を定義できます。


解決策2:自分でサイズを変更する

他の問題がありました:画像を回転する必要がある場合があります(それは本当に頻繁に起こります)。そのためには、EXIF方向タグを使用する必要があります。サイズを変更すると明らかに失われるため、サイズを変更する前にフロントエンドでこの情報をフェッチする必要があります。そのために、私は Exif.jsライブラリ を使用しました。

これが JSFiddleの使用例 です。サイズが変更された画像のデータURIがコンソールに表示されます。

3
Elzéar

OK。サイズ変更を実装する方法を見つけるのに少し時間がかかりました。

これは私のために働く最終的な解決策です:

Import css and dropzone.js

<div class="row">
    <div class="col-sm-20 well">
        <form action="@Url.Action("_UploadImages", "Notebooks", new { unique = Model.UniqueId })" 
              method="post" 
              enctype="multipart/form-data"
              class="dropzone"
              id="my-dropzone"></form>
    </div>
</div>

<script type="text/javascript">
    Dropzone.options.myDropzone = {
        url: '@Url.Action("_UploadImages", "Notebooks", new { unique = Model.UniqueId })',
        autoProcessQueue: true,
        uploadMultiple: true,
        parallelUploads: 3,
        maxFilesize: 10,
        resizeWidth: 2048,
        addRemoveLinks: false,
        init: function () {
        }
    }
</script>
1
HerGiz