0

我正在使用 fileupload jQuery 插件将文件上传到我的网站。我想在上传之前调整图像大小以最大程度地减少网络使用,但到目前为止我找不到完整的示例。这是我的简单测试代码。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="/static/js/cloudinary/jquery.ui.widget.js" type="text/javascript"></script>
<script src="/static/js/cloudinary/load-image.min.js" type="text/javascript"></script>
<script src="/static/js/cloudinary/canvas-to-blob.min.js" type="text/javascript"></script>
<script src="/static/js/cloudinary/jquery.iframe-transport.js" type="text/javascript"></script>
<script src="/static/js/cloudinary/jquery.fileupload.js" type="text/javascript"></script>
<script src="/static/js/cloudinary/jquery.fileupload-ip.js" type="text/javascript"></script>
<script src="/static/js/cloudinary/jquery.fileupload-process.js" type="text/javascript"></script>
<script src="/static/js/cloudinary/jquery.fileupload-validate.js" type="text/javascript"></script>

...

$("#fileupload")
    .fileupload({
        disableImageResize: false,
        imageMaxWidth: 8000,
        imageMaxHeight: 6000,
        acceptFileTypes: /(\.|\/)(gif|jpe?g|png|bmp|ico)$/i,
        maxFileSize: 20000000, // 20MB
        process: [
            {
                action: 'load',
                fileTypes: /^image\/(gif|jpeg|png)$/,
                maxFileSize: 20000000 // 20MB
            },
            {
                action: 'resize',
                maxWidth: 200,
                maxHeight: 150,
                minWidth: 80,
                minHeight: 60
            },
            {
                action: 'save'
            }
        ]

    });
4

3 回答 3

1

jQuery 拖放文件上传 | Bootstrap 图像上传和预览

// Code By Webdevtrick ( https://webdevtrick.com )
function readFile(input) {
  if (input.files && input.files[0]) {
    var reader = new FileReader();

    reader.onload = function(e) {
      var htmlPreview =
        '<img width="200" src="' + e.target.result + '" />' +
        '<p>' + input.files[0].name + '</p>';
      var wrapperZone = $(input).parent();
      var previewZone = $(input).parent().parent().find('.preview-zone');
      var boxZone = $(input).parent().parent().find('.preview-zone').find('.box').find('.box-body');

      wrapperZone.removeClass('dragover');
      previewZone.removeClass('hidden');
      boxZone.empty();
      boxZone.append(htmlPreview);
    };

    reader.readAsDataURL(input.files[0]);
  }
}

function reset(e) {
  e.wrap('<form>').closest('form').get(0).reset();
  e.unwrap();
}

$(".dropzone").change(function() {
  readFile(this);
});

$('.dropzone-wrapper').on('dragover', function(e) {
  e.preventDefault();
  e.stopPropagation();
  $(this).addClass('dragover');
});

$('.dropzone-wrapper').on('dragleave', function(e) {
  e.preventDefault();
  e.stopPropagation();
  $(this).removeClass('dragover');
});

$('.remove-preview').on('click', function() {
  var boxZone = $(this).parents('.preview-zone').find('.box-body');
  var previewZone = $(this).parents('.preview-zone');
  var dropzone = $(this).parents('.form-group').find('.dropzone');
  boxZone.empty();
  previewZone.addClass('hidden');
  reset(dropzone);
});
/* Code By Webdevtrick ( https://webdevtrick.com ) */
.container {
  padding: 50px 10%;
}

.box {
  position: relative;
  background: #ffffff;
  width: 100%;
}

.box-header {
  color: #444;
  display: block;
  padding: 10px;
  position: relative;
  border-bottom: 1px solid #f4f4f4;
  margin-bottom: 10px;
}

.box-tools {
  position: absolute;
  right: 10px;
  top: 5px;
}

.dropzone-wrapper {
  border: 2px dashed #91b0b3;
  color: #92b0b3;
  position: relative;
  height: 150px;
}

.dropzone-desc {
  position: absolute;
  margin: 0 auto;
  left: 0;
  right: 0;
  text-align: center;
  width: 40%;
  top: 50px;
  font-size: 16px;
}

.dropzone,
.dropzone:focus {
  position: absolute;
  outline: none !important;
  width: 100%;
  height: 150px;
  cursor: pointer;
  opacity: 0;
}

.dropzone-wrapper:hover,
.dropzone-wrapper.dragover {
  background: #ecf0f5;
}

.preview-zone {
  text-align: center;
}

.preview-zone .box {
  box-shadow: none;
  border-radius: 0;
  margin-bottom: 0;
}

.btn-primary {
  background-color: crimson;
  border: 1px solid #212121;
}
<!DOCTYPE html>
<!-- Code By Webdevtrick ( https://webdevtrick.com ) -->
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Drag and Drop Image Upload | Webdevtrick.com</title>
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css'>
  <link rel="stylesheet" href="style.css">

</head>
<body>

<section>
  <form action="" method="POST" enctype="multipart/form-data">
    <div class="container">
      <div class="row">
        <div class="col-md-12">
          <div class="form-group">
            <label class="control-label">Upload File</label>
            <div class="preview-zone hidden">
              <div class="box box-solid">
                <div class="box-header with-border">
                  <div><b>Preview</b></div>
                  <div class="box-tools pull-right">
                    <button type="button" class="btn btn-danger btn-xs remove-preview">
                      <i class="fa fa-times"></i> Reset The Field
                    </button>
                  </div>
                </div>
                <div class="box-body"></div>
              </div>
            </div>
            <div class="dropzone-wrapper">
              <div class="dropzone-desc">
                <i class="glyphicon glyphicon-download-alt"></i>
                <p>Choose an image file or drag it here.</p>
              </div>
              <input type="file" name="img_logo" class="dropzone">
            </div>
          </div>
        </div>
      </div>

      <div class="row">
        <div class="col-md-12">
          <button type="submit" class="btn btn-primary pull-right">Upload</button>
        </div>
      </div>
    </div>
  </form>
</section>


<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js'></script>
<script  src="function.js"></script>

</body>
</html>

于 2019-11-28T08:06:46.347 回答
0

As putting all the pieces together working for a complex uploader is a complex task, I share here my solution.

The elements of this answer

  • There can be arbitrary number of uploaders per page. In this example there are two separate upload buttons on the page, called driving and medical.

  • Resize the image to 1024 x 1024 on the client-side before uploading

  • Show preview of uploaded image for the user during the upload

  • HTML code as Jinja 2 templates

  • Bootstrap 3.x themed upload button and progress bar for the upload

  • Pyramid style JavaScript resource loading

Jinja 2 HTML template code which renders one individual upload widget (upload_snippet.html), it takes parameters id and name and upload_target:

<div id="upload-{{ id }}">

    <div id="medical-license" class="btn btn-block btn-file">
        <i class="fa fa-camera"></i> {{ name }}

        <input type="file" class="file-select" data-url="{{ upload_target }}" data-param-name="{{ id }}">
    </div>
    <p>
        <div class="preview" style="display: none"></div>
    </p>

    <div class="progress progress-xxx" style="display: none">
        <div class="progress-bar progress-bar-striped progress-bar-xxx active" role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
        </div>
    </div>

    <div class="success" style="display: none">

        <div class="alert alert-success">
            {{ name }} upload completed
        </div>
    </div>

    <div class="error" style="display: none">

        <div class="alert alert-danger">
            <span class="error-message"></span>
        </div>
    </div>
</div>

The main Jinja 2HTML template which constructs two upload widgets. It styles them to look like Bootstrap buttons:

{% extends "site/base.html" %}

{% block extra_head %}
    <style>
    /* http://www.abeautifulsite.net/whipping-file-inputs-into-shape-with-bootstrap-3/ */
    .btn-file {
        position: relative;
        overflow: hidden;
    }
    .btn-file input[type=file] {
        position: absolute;
        top: 0;
        right: 0;
        min-width: 100%;
        min-height: 100%;
        font-size: 100px;
        text-align: right;
        filter: alpha(opacity=0);
        opacity: 0;
        outline: none;
        background: white;
        cursor: inherit;
        display: block;
    }

    .preview {
        width: 128px;
        height: 128px;
        margin: 0 auto;
    }
    </style>
{% endblock %}

{% block content_section %}
    <!-- Header -->
    <section id="license-information">

        <div class="row">
            <div class="col-md-12">
                 <h1>Upload information</h1>
            </div>
        </div>

        <div class="row">
            <div class="col-md-6">

                {% with id='medical', name='Medical license' %}
                    {% include "upload_snippet.html" %}
                {% endwith %}

                {% with id='driving', name='Driving license or other id' %}
                    {% include "upload_snippet.html" %}
                {% endwith %}


            </div>
        </div>

    </section>
{% endblock content_section %}

{% block custom_script %}

 <!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="{{ 'xxx:static/jquery-file-upload/js/vendor/jquery.ui.widget.js'| static_url }}"></script>

<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<script src="{{ 'xxx:static/jquery-file-upload/js/load-image.all.min.js' | static_url }}"></script>

<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="{{ 'xxx:static/jquery-file-upload/js/canvas-to-blob.js' | static_url }}"></script>

<!-- The basic File Upload plugin -->
<script src="{{ 'xxx:static/jquery-file-upload/js/jquery.fileupload.js' | static_url }}"></script>
<!-- The File Upload processing plugin -->
<script src="{{ 'xxx:static/jquery-file-upload/js/jquery.fileupload-process.js' | static_url }} "></script>
<!-- The File Upload image preview & resize plugin -->
<script src="{{ 'xxx:static/jquery-file-upload/js/jquery.fileupload-image.js' | static_url }} "></script>

<script>
window.nextURL = "{{ after_both_files_are_uploaded }}"
</script>

<script>
    "use strict";

    var state = {
        medical: false,
        driving: false
    }

    // Make styled elements to trigger file input
    $(document).on('change', '.btn-file :file', function() {
        var input = $(this),
            numFiles = input.get(0).files ? input.get(0).files.length : 1,
            label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
        input.trigger('fileselect', [numFiles, label]);
    });

    function checkForward() {
        // Is all upload done and we can go to the next page?
        if(state.medical && state.driving) {
            window.location = window.nextURL;
        }
    }

    function doUpload(name) {

        var baseElem = $("#upload-" + name);

        if(baseElem.length != 1) {
            throw new Error("Wooops, bad DOM tree");
        }

        function onStart() {
            baseElem.find(".progress").show();
            baseElem.find(".error").hide();
            baseElem.find(".success").hide();
        }

        function onDone(result, data) {
            baseElem.find(".progress").hide();
            if(data.result.status == "ok") {
                // All ok, check if we can proceed
                baseElem.find(".success").show();
                state[name] = true;
                checkForward();
            } else {
                // Server responded us it didn't like the file and gave a specific error message
                var msg = data.result.message;
                baseElem.find(".error-message").text(msg);
                baseElem.find(".error").show();
                state[name] = false;
            }
        }

        function onError(result, data) {
            baseElem.find(".progress").hide();
            baseElem.find(".error-message").text("Upload could not be completed. Please contact the support.");
            baseElem.find(".error").show();
            state[name] = false;
        }

        function onProgress(e, data) {
            var progress = parseInt(data.loaded / data.total * 100, 10);
            baseElem.find(".progress-bar").css("width", progress + "%");
        }

        function onPreview(e, data) {
            var canvas = data.files[0].preview;
            var dataURL = canvas.toDataURL();
            baseElem.find(".preview").css("background-image", 'url(' + dataURL +')');
            baseElem.find(".preview").css({width: canvas.width, height: canvas.height});
            baseElem.find(".preview").show();
        }

        var upload = baseElem.find('.file-select');
        upload.fileupload({
            dataType: 'json',
            // Enable image resizing, except for Android and Opera,
            // which actually support image resizing, but fail to
            // send Blob objects via XHR requests:
            // disableImageResize: /Android(?!.*Chrome)|Opera/
            //    .test(window.navigator && navigator.userAgent),
            disableImageResize: false,
            imageMaxWidth: 1024,
            imageMaxHeight: 1024,
            imageCrop: false, // Force cropped images,
            previewMaxWidth: 128,
            previewMaxHeight: 128,
            maxFileSize: 7*1024*1024
        });

        upload.bind("fileuploaddone", onDone);
        upload.bind("fileuploadstart", onStart);
        upload.bind("fileuploadfail", onError);
        upload.bind("fileuploadprogress", onProgress);
        upload.bind('fileuploadprocessalways', onPreview);

    }

    $(document).ready(function() {
        doUpload("medical");
        doUpload("driving");
    });
</script>

{% endblock %}

Then a simple server-side Pyramid view which decodes the payload and checks the user uploaded an image and not a random file. The result is an JSON response which JavaScript can decode:

@view_config(route_name='upload_target', renderer='json')
def upload_target(request):
    """AJAX upload of driving license and medical images."""
    if "medical" in request.params:
        license = "medical"
        files = request.params["medical"]
    elif "driving" in request.params:
        license = "driving"
        files = request.params["driving"]
    else:
        raise RuntimeError("Unsupported upload type")

    # # TODO: use chunks, do not buffer 100%
    # path = user.prepare_upload_path()
    storage = io.open(where_to_save, "wb")
    fp = files.file

    # Now we test for a valid image upload
    image_test = imghdr.what(fp)
    if image_test == None:
        return {"status": "fail", "message": "Only JPEG and PNG image file upload supported."}

    fp.seek(0)
    data = fp.read()
    assert len(data) > 0
    storage.write(data)
    storage.close()

    return {"status": "ok"}
于 2015-04-26T19:25:16.747 回答
0

我有一个类似的问题,我认为这是由于没有 canvas-to-blob.js。添加该脚本,让它工作。我用的是铬。在 github 上看到这个问题:

https://github.com/blueimp/jQuery-File-Upload/issues/2665

此外,您可能也不需要描述整个处理管道描述,因为 jquery 文件上传会根据某些参数的存在构建必要的阶段。

于 2014-01-10T04:10:08.477 回答