代码之家  ›  专栏  ›  技术社区  ›  Samir Tendulkar

如何在使用javascript提交之前调整Django Imagefield中图像的大小

  •  0
  • Samir Tendulkar  · 技术社区  · 7 年前

    简介: 我有一篇帖子,用户最多可以上传8张图片。我的部署方法不允许我的总上载(所有图像的总大小超过10mb)。因此,我不能使用枕头或其他软件包,减少上传后的图像大小。我在想,如果我使用Javascript,我甚至可以在提交表单之前减小图像大小。这样,当我点击submit时,图像已经减少,所有图像的总大小小于9mb(为了安全起见)

    使用 https://github.com/josefrichter/resize/blob/master/public/preprocess.js

    我不知道如何使用它们。下面是我的表单模板

    {% extends 'posts/post_base.html' %}
    {% load bootstrap3 %}
    {% load staticfiles %}    
    {% block postcontent %}
    
    <h2> Add a new Post</h2>
    <form action="" method="post" enctype="multipart/form-data" id="form">
        {% csrf_token %}
        {% bootstrap_form form %}
        <img id="preview" src="" width="100" />
        {{formset.management_form}}
        {% for f in formset %}
            <div style="border-style: inset; padding:20px;">
              <p class="text-warning">Extra Image {{forloop.counter}}</p>
              {% bootstrap_form f %}
              <img src="" width="60" id="preview-extra{{forloop.counter}}"/>
            </div>
        {% endfor %}
    
        <br/><br/><input type="submit" class="btn btn-primary" value="Post"/>
    
    </form>
    
    
    <script >
    
    var fileinput = document.getElementById('fileinput');
    
    var max_width = 500;
    var max_height = 500;
    
    var preview = document.getElementById('preview');
    
    var form = document.getElementById('form');
    
    function processfile(file) {
    
        if( !( /image/i ).test( file.type ) )
            {
                alert( "File "+ file.name +" is not an image." );
                return false;
            }
    
        // read the files
        var reader = new FileReader();
        reader.readAsArrayBuffer(file);
    
        reader.onload = function (event) {
          // blob stuff
          var blob = new Blob([event.target.result]); // create blob...
          window.URL = window.URL || window.webkitURL;
          var blobURL = window.URL.createObjectURL(blob); // and get it is URL
    
          // helper Image object
          var image = new Image();
          image.src = blobURL;
          //preview.appendChild(image); // preview commented out, I am using the canvas instead
          image.onload = function() {
            // have to wait till it is loaded
            var resized = resizeMe(image); // send it to canvas
            var newinput = document.createElement("input");
            newinput.type = 'hidden';
            newinput.name = 'images[]';
            newinput.value = resized; // put result from canvas into new hidden input
            form.appendChild(newinput);
          }
        };
    }
    
    function readfiles(files) {
    
        // remove the existing canvases and hidden inputs if user re-selects new pics
        var existinginputs = document.getElementsByName('images[]');
        var existingcanvases = document.getElementsByTagName('canvas');
        // it is a live list so removing the first element each time DOMNode.prototype.remove = function() {this.parentNode.removeChild(this);}
        while (existinginputs.length > 0) {
          form.removeChild(existinginputs[0]);
          preview.removeChild(existingcanvases[0]);
        }
    
        for (var i = 0; i < files.length; i++) {
          processfile(files[i]); // process each file at once
        }
        fileinput.value = ""; //remove the original files from fileinput
        // TODO remove the previous hidden inputs if user selects other files
    }
    
    // this is where it starts. event triggered when user selects files
    fileinput.onchange = function(){
      if ( !( window.File && window.FileReader && window.FileList && window.Blob ) ) {
        alert('The File APIs are not fully supported in this browser.');
        return false;
        }
      readfiles(fileinput.files);
    };
    
    // === RESIZE ====
    
    function resizeMe(img) {
    
      var canvas = document.createElement('canvas');
    
      var width = img.width;
      var height = img.height;
    
      // calculate the width and height, constraining the proportions
      if (width > height) {
        if (width > max_width) {
          //height *= max_width / width;
          height = Math.round(height *= max_width / width);
          width = max_width;
        }
      } else {
        if (height > max_height) {
          //width *= max_height / height;
          width = Math.round(width *= max_height / height);
          height = max_height;
        }
      }
    
      // resize the canvas and draw the image data into it
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, width, height);
    
      preview.appendChild(canvas); // do the actual resized preview
    
      return canvas.toDataURL("image/jpeg",0.7); // get the data from canvas as 70% JPG (can be also PNG, etc.)
    
    }
    </script>
    {% endblock %}
    

    我希望图像大小减少到400kb。如果用户上载的内容少于此值,则无需调整大小

    enter image description here

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  1
  •   M.javid munsu    7 年前

    以下代码部分可帮助您解决此问题:

    views.py:

    import re
    import io
    import base64
    
    from django.core.files import File
    from django.shortcuts import render
    
    from .forms import StoreImageForm
    
    
    def upload_canvas(request):
        form = StoreImageForm()
        if request.method == 'POST':
            image_base64 = request.POST.get('image_base64', '')
            res = re.match(r'^([^,]*),(.*)$', image_base64)
            if res:
                ext = re.match(r'^data:image/(.+);base64$', res.groups()[0]).groups()[0]
                image = base64.b64decode(res.groups()[-1])
                buf = io.BytesIO(image)
                form = StoreImageForm(files={'upload_file': File(buf, name=f'name.{ext}')})
                try:
                    form.is_valid()
                except Exception as err:
                    return render(request, 'form.html', {'message': err, 'form': form})
                instance = form.save()
                return render(request, 'form.html', {'message': 'Image Uploaded Successfuly', 'form': form})
            return render(request, 'form.html', {'message': 'Image Upload Failed', 'form': form})
        return render(request, 'form.html', {'message': 'Upload Image...', 'form': form})
    

    form.html:

    <html>
        <head>
            <title>Upload Canvas</title>
            <script lang="javascript">
                function resize_image(event) {
                    var canvas = document.getElementById("my_canvas");
                    var ctx = canvas.getContext("2d");
                    var reader = new FileReader();
                    var img = new Image();
                    var type = '';
                    var ratio = 1;
    
                    img.onerror = function(e) {
                      console.log("Not ok", e);
                    }
    
                    img.onload = function (img_onload_event) {
                        canvas.height = canvas.width * (img.height / img.width);
    
                        // step 1 - resize to 50%
                        var oc = document.createElement('canvas'),
                            octx = oc.getContext('2d');
    
                        oc.width = img.width * ratio;
                        oc.height = img.height * ratio;
                        octx.drawImage(img, 0, 0, oc.width, oc.height);
    
                        // step 2
                        octx.drawImage(oc, 0, 0, oc.width, oc.height);
    
                        // step 3, resize to final size
                        ctx.drawImage(oc, 0, 0, oc.width, oc.height, 0, 0, canvas.width, canvas.height);
    
                        var dataURL = oc.toDataURL(type, ratio)
                        // var blob = dataURItoBlob(dataURL)
    
                        b64 = dataURL;
                        padding = (b64.charAt(b64.length - 2) === '=') ? 2 : ((b64.charAt(b64.length - 1) === '=') ? 1 : 0);
                        fileSize = (b64.length * 0.75 - padding) / 1024;
                        if(fileSize > 500) {
                            img.src = b64;
                            return;
                        }
    
                        var my_image_base64 = document.getElementById('my_image_base64')
                        my_image_base64.setAttribute("value", dataURL)
                    }
    
                    reader.onload = function (e) {
                        b64 = reader.result;
                        padding = (b64.charAt(b64.length - 2) === '=') ? 2 : ((b64.charAt(b64.length - 1) === '=') ? 1 : 0);
                        fileSize = (b64.length * 0.75 - padding) / 1024;
                        if(fileSize > 500){
                            ratio = 0.8
                        }
    
                        img.src = e.target.result;
                    }
                    type = event.target.files[0].type || 'image/jpeg';
                    reader.readAsDataURL(event.target.files[0]);
                }
    
    
                window.onload = function(){
                    document.getElementById('my_image').addEventListener('change', resize_image, false);
                }
            </script>
        </head>
    
        <body>
            <h2>{{ message }}</h2>
            <form method="post">
                {% csrf_token %}
                <input  type="file"  id="my_image" />
                <input  type="hidden" id="my_image_base64" name="image_base64" />
                <button id="upload_button"> Upload </button>
            </form>
            <br/>
            <canvas id="my_canvas" width="500" />
        </body>
    </html>
    

    forms.py:

    from django import forms
    
    from .models import UploadModel
    
    
    class StoreImageForm(forms.ModelForm):
        class Meta:
            model = UploadModel
            fields = ['upload_file']
    

    from django.db import models
    
    
    class UploadModel(models.Model):
        upload_file = models.ImageField()
    

    image-minimizer-uploader github中的项目。