Изменение размера на стороне клиента с помощью JQuery fileupload

0

Я использую plugup для 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'
            }
        ]

    });
Теги:
jquery-file-upload

2 ответа

0

Поскольку объединение всех частей вместе для сложного загрузчика - сложная задача, я разделяю здесь свое решение.

Элементы этого ответа

  • На страницу может быть произвольное количество пользователей. В этом примере на странице есть две отдельные кнопки загрузки, называемые вождением и медицинскими.

  • Измените размер изображения на 1024 x 1024 на стороне клиента перед загрузкой

  • Показывать предварительный просмотр загруженного изображения для пользователя во время загрузки

  • HTML-код как шаблон Jinja 2

  • Загрузочная кнопка загрузки 3.x и индикатор выполнения для загрузки

  • Загрузка ресурса JavaScript в стиле Pyramid

Jinja 2 HTML-код шаблона, который отображает один отдельный виджет загрузки (upload_snippet.html), upload_snippet.html идентификаторы параметров и имя и 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>

Основной шаблон Jinja 2HTML, который создает два загрузочных виджета. Он стилирует их как кнопки Bootstrap:

{% 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 %}

Затем простое представление Pyramid на стороне сервера, которое декодирует полезную нагрузку и проверяет загрузку пользователем изображения, а не случайный файл. Результатом является ответ JSON, который JavaScript может декодировать:

@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"}
0

У меня была аналогичная проблема, которая, по моему мнению, была вызвана отсутствием canvas-to-blob.js. Добавив этот скрипт, он начал работать. Я использовал хром. См. Эту проблему в github:

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

Кроме того, вам, вероятно, также не нужно описывать описание всего процесса конвейера, поскольку загрузка файла jquery создает необходимые этапы, основанные на наличии определенных параметров.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню