Подтвердить что ты не робот

Загрузка IOS6 и Safari - Файл API + Холст + jQuery Ajax Загрузка и изменение размера файлов асинхронно

IOS6 был выпущен, и я тестировал загрузку фотографий.

Он работает хорошо, но с большими изображениями через 3G он SLOW, как ожидалось.

Благодаря File API и Canvas можно изменять размер изображений с помощью JavaScript. Я надеюсь, что, если я изменил размер изображений до того, как попытаюсь их загрузить, они будут загружаться быстрее - при условии быстрого доступа пользователей. С процессорами смартфонов, которые экспоненциально растут быстрее, чем скорость сети, я считаю, что это решение является победителем.

Николас предложил отличное решение для изменения размера изображения:

Изменение размера изображения перед загрузкой

Тем не менее, у меня сложнее всего реализовать его с помощью jQuery Ajax. Любые советы или помощь приветствуются, так как этот код, вероятно, будет чрезвычайно полезен для разработки мобильных веб-приложений после IOS6.

var fileType = file.type,
    reader = new FileReader();

reader.onloadend = function () {
    var image = new Image();
    image.src = reader.result;

    image.onload = function () {

        //Detect image size
        var maxWidth = 960,
            maxHeight = 960,
            imageWidth = image.width,
            imageHeight = image.height;
        if (imageWidth > imageHeight) {
            if (imageWidth > maxWidth) {
                imageHeight *= maxWidth / imageWidth;
                imageWidth = maxWidth;
            }
        } else {
            if (imageHeight > maxHeight) {
                imageWidth *= maxHeight / imageHeight;
                imageHeight = maxHeight;
            }
        }

        //Create canvas with new image
        var canvas = document.createElement('canvas');
        canvas.width = imageWidth;
        canvas.height = imageHeight;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0, imageWidth, imageHeight);

        // The resized file ready for upload
        var finalFile = canvas.toDataURL(fileType);

        if (formdata) {

            formdata.append("images[]", finalFile);

            $.ajax({
                url: "upload.php",
                type: "POST",
                data: formdata,
                dataType: 'json',
                processData: false,
                contentType: false,
                success: function (res) {
                    //successful image upload
                }
            });

        }
    }
}
reader.readAsDataURL(file);
4b9b3361

Ответ 1

Я только что разработал плагин jQuery для изменения размера изображения canvas на стороне клиента . Он также обрабатывает ориентацию и проблему iOS6 squashed image.

Вы можете попробовать: http://gokercebeci.com/dev/canvasresize

Использование:

$.canvasResize(file, {
               width   : 300,
               height  : 0,
               crop    : false,
               quality : 80,
               callback: function(dataURL, width, height){

                         // your code

               }
});

Ответ 2

Я работал с функцией загрузки со второй бета-версии iOS6. Для меня работает следующий код:

Поместите это в начало своей HTML-страницы -

<script>window.onload = function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");

var fileSelect = document.getElementById("fileSelect"),
    input = document.getElementById("input");

    input.addEventListener("change", handleFiles);

    //hides ugly default file input button  
    fileSelect.addEventListener("click", function (e) {
        if (input) {
            input.click();
        }
        e.preventDefault();
    }, false);

function handleFiles(e) {
    var reader = new FileReader;
    reader.onload = function (event) {
        var img = new Image();
        img.src = reader.result;
        img.onload = function () {
            var maxWidth = 320,
                maxHeight = 350,
                imageWidth = img.width,
                imageHeight = img.height;

            if (imageWidth > imageHeight) {
                if (imageWidth > maxWidth) {
                    imageHeight *= maxWidth / imageWidth;
                    imageWidth = maxWidth;
                }
            } else {
                if (imageHeight > maxHeight) {
                    imageWidth *= maxHeight / imageHeight;
                    imageHeight = maxHeight;
                }
            }
            canvas.width = imageWidth;
            canvas.height = imageHeight;

            ctx.drawImage(this, 0, 0, imageWidth, imageHeight);

            // The resized file ready for upload
            var finalFile = canvas.toDataURL("image/png");

            var postData = 'canvasData=' + finalFile;
            var ajax = new XMLHttpRequest();
            ajax.open('POST', 'save.php', true);
            ajax.setRequestHeader('Content-Type', 'canvas/upload');

            ajax.onreadystatechange = function () {
                if (ajax.readyState == 4) {
                    //just to visually confirm it worked...
                    window.open(canvas.toDataURL("image/png"), "mywindow");
                }
            }
            ajax.send(postData);
        }
    }
    reader.readAsDataURL(e.target.files[0]);
}
}
</script>

Здесь HTML -

 <div style="width:320px;position:absolute;z-index:9;top:387px;">
<button style="width:60px;" id="fileSelect">upload</button>
<input type="file" id="input" name="input" accept="image/*" style="display:none;"></div>

Здесь PHP -

<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
    // Get the data
   $imageData=$GLOBALS['HTTP_RAW_POST_DATA'];

   // Remove the headers (data:,) part.  
   // A real application should use them according to needs such as to check image type
   $filteredData=substr($imageData, strpos($imageData, ",")+1);

   // Need to decode before saving since the data we received is already base64 encoded
   $unencodedData=base64_decode($filteredData);

   // Save file.  This example uses a hard coded filename for testing, 
   // but a real application can specify filename in POST variable
   $fp = fopen( 'users/user_photo.png', 'wb' );
   fwrite( $fp, $unencodedData);
   fclose( $fp );
 }
 ?>

Единственная проблема, с которой я столкнулся, - это получать изображения с камеры без поворота на 90 градусов.

Надеюсь, что это поможет, сообщите мне, есть ли у вас какие-либо проблемы с кодом (это мой первый пост).

Ответ 3

Учитывая, что мы имеем дело с большими проблемами с изображениями и памятью в мобильном браузере, я хотел посмотреть, можно ли найти легкое решение, позволяющее избежать создания дублирующего холста и выполнять другие операции с изображениями только для обнаружения и изменения размера.

Кажется, что если Mobile Safari вертикально сквозит изображение, которое слишком велико, отношение к тому, насколько оно это делает, остается прежним.

Итак, прямо сейчас, прежде чем я даже сделаю изображение на холсте, я использую очень быстрое эмпирическое правило, в котором я просто проверяю, является ли браузер мобильной iDevice navigator.userAgent.match(/(iPod|iPhone|iPad)/) ... И высота или ширина изображения больше 2000 пикселей, и в этом случае я знаю, что он будет раздавлен. В этом случае в canvasContext.drawImage() я определяю высоту изображения на 4 раза выше, чем обычно должен был быть для заданного объектного изменения размера изображения. Основываясь на том, что я видел, Mobile Safari копирует изображение в 4 раза.

Затем я визуализую изображение, и он делает неискаженный первый раз, сбрасывая предварительно растянутое изображение обратно до того, что затем становится нормальной пропорцией X: Y. Без каких-либо дополнительных элементов холста или контекстов или тестовых рендерингов или итераций пикселей, которые упоминаются выше в 100% -ном решении, используется.

Я уверен, что могут быть некоторые случаи кросс, и ограничение размера изображения может быть неточным, но для моего приложения мне нужно решение, которое было FAST.