2015-02-11 2 views
0

Я пытаюсь создать сценарий загрузки, который изменяет размер клиентской части нескольких изображений до того, как будет обработано saveimage.php. Причина этого в том, что они будут загружены в другом месте, где может быть очень медленный интернет.Загрузите несколько изображений холста через цикл javascript

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

В настоящее время он проверяет, когда файлы вводятся в поле «file_input». Затем он просматривает количество файлов и просматривает их до тех пор, пока каждый файл не будет помещен в холст и не будет загружен, пока он там.

Однако проблема заключается в следующем:, когда я не добавляю предупреждение для каждого файла, цикл идет слишком быстро и обрабатывает только 1 или 2 из 10 изображений, например. Поскольку сценарий загрузки будет работать быстрее, чем холст может быть обновлен с новым изображением.

Это моя текущая страница, упрощена до ядра:

<!DOCTYPE html> 
<html> 
<head> 
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 
</head> 
<body> 

<form> 
    <input id="file_input" type='file' multiple /> 
</form> 

<div id="preview"> 
    <canvas id="canvas"></canvas> 
</div> 

<script> 

    var input = document.getElementById('file_input'); 
    input.addEventListener('change', handleFiles); 

    function handleFiles(e) { 

     var files = input.files; 
     alert(files.length +" files are being uploaded!"); // display amount of files for testing purpose 

     for (var i = 0; i < files.length; ++i) { 

      alert("Upload file number: "+i); // display file # for testing purpose, when this is removed the script will go too fast 

      var MAX_HEIGHT = 1000; 
      var ctx = document.getElementById('canvas').getContext('2d'); 
      var img = new Image; 

      img.onload = function(){ 
       if(img.height > MAX_HEIGHT) { 
        img.width *= MAX_HEIGHT/img.height; 
        img.height = MAX_HEIGHT; 
       } 
       var ctx = canvas.getContext("2d"); 
       ctx.clearRect(0, 0, canvas.width, canvas.height); 
       preview.style.width = img.width + "px"; 
       preview.style.height = img.height + "px"; 
       canvas.width = img.width; 
       canvas.height = img.height; 
       ctx.drawImage(img, 0, 0, img.width, img.height); 

       // the canvas should contain an image now and this will send it through saveimage.php 
       var myDrawing = document.getElementById("canvas"); 
       var drawingString = myDrawing.toDataURL("image/jpeg", 0.5); 
       var postData = "canvasData="+drawingString; 
       var ajax = new XMLHttpRequest(); 
       ajax.open("POST",'saveimage.php',true); 
       ajax.setRequestHeader('Content-Type', 'canvas/upload'); 
       ajax.onreadystatechange=function() 
        { 
         if (ajax.readyState == 4); 
        } 
        ajax.send(postData); 
      }; 

      img.src = URL.createObjectURL(e.target.files[i]); 
     } 
    } 

</script> 

</body> 
</html> 

И это мой saveimage.php, который хорошо работает, но только для полного обзора:

<?php 

if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) 
{ 
    $rawImage=$GLOBALS['HTTP_RAW_POST_DATA']; 
    $removeHeaders=substr($rawImage, strpos($rawImage, ",")+1); 
    $decode=base64_decode($removeHeaders); 

    // check if the file already exists and keep adding +1 intil it's unique 
    $i = 1; 
    while(file_exists('uploads/image'.$i.'.jpg')) {   
     $i++; 
    } 

    $fopen = fopen('uploads/image'.$i.'.jpg', 'wb'); 
    fwrite($fopen, $decode); 
    fclose($fopen); 

} 

?> 

Немного дополнительной информации:

  • Я добавил холст, потому что, насколько я понимаю, это только способ изменить размер изображения на стороне клиента. В финальном скрипте будет установлено .
  • Если холст может быть пропущен и данные отправлены в saveimage.php сразу же это решит проблему тоже, я думаю.
  • Как я уже сказал, я не очень разбираюсь в javascript, поэтому, если есть гораздо более простой способ достижения этой цели. Пожалуйста, дайте мне знать!

Заранее благодарен!

+0

Перед выполнением чего-либо еще: установите обработчик onload * before *, установите src. – GameAlchemist

+0

@GameAlchemist Я поместил обработчик onload перед src сейчас, он все еще функционирует одинаково, в чем причина? – Pascal

ответ

1

JavaScript загружает изображение асинхронно. Это означает, что после того, как ему назначено новое изображение .src, он начнет загрузку изображения, но одновременно продолжит обработку javascript после .src, пока изображение занимает время для загрузки.

Вы используете одну и ту же переменную изображения (var img) внутри цикла for. Поэтому каждый раз через цикл вы переписываете предыдущий img до того, как предыдущее изображение было полностью загружено.

Вот образом загрузчик, который полностью загружает все изображения, а затем вызывает функцию запуска(), где вы можете сделать вы обработку:

// image loader 

// put the paths to your images in imageURLs[] 
var imageURLs=[]; 
imageURLs.push("myImage1.png"); 
imageURLs.push("myImage2.png"); 
// etc, etc. 

// the loaded images will be placed in imgs[] 
var imgs=[]; 

var imagesOK=0; 
loadAllImages(start); 

function loadAllImages(callback){ 
    for (var i=0; i<imageURLs.length; i++) { 
     var img = new Image(); 
     imgs.push(img); 
     img.onload = function(){ 
      imagesOK++; 
      if (imagesOK>=imageURLs.length) { 
       callback(); 
      } 
     }; 
     img.onerror=function(){alert("image load failed");} 
     img.crossOrigin="anonymous"; 
     img.src = imageURLs[i]; 
    }  
} 

function start(){ 

    // the imgs[] array now holds fully loaded images 
    // the imgs[] are in the same order as imageURLs[] 

} 
0

В OnLoad обратного вызова использовать this ключевое слово (вместо img), чтобы для текущего изображения, img может/будет переписан в течение цикла обратного вызова до того, как пожары.
img.height --> this.height etc
Также есть причина, по которой вы используете настраиваемый тип контента вместо application/x-www-form-urlencoded?
Данные, закодированные в Url, намного легче работать.

0

я боролся с той же проблемой в течение некоторого времени, но я, наконец, cobbled вместе другое решение, используя бит кода от других, которые решили эту проблему, и он работает. Это может быть не идеально, и я бы приветствовал любые предложения по улучшению. Концепция состоит в том, что у вас есть два Javascript Функции, которые являются идентификаторами Resize0 и Resize1, и они называют друг друга , пока все фотографии не будут изменены, тогда функция, которая изменяет размер Последнее изображение Присылает форму. Две функции передают параметры между друг с другом, так что один из них узнает, когда отправить форму. Два из этих параметров: Number_Of_Images и текущий Image_Number. Вы также можете загрузить рабочую веб-страницу примера от http://www.wantitconsulting.co.nz/ExampleResizeUpload.zip. Вам нужно будет создать папку в базовом каталоге вашего тестового веб-сайта для изображений. Имя папки - TestResizeUpload. Сервер использует php.

0

У меня была одна и та же проблема, но мне удалось это сделать, сначала отобразив все изображения в скрытом теге «img», взяв за ссылку этот пост «HTML5 to display uploaded image untill next one is uploaded?», после чего я запускаю функцию с дополнительным кнопка, которая использует последние созданные изображения и сделать все из них в отделенном холсте, которые также были созданы в то же время, что изображения, где загрузка, код будет выглядеть следующим образом

HTML-:

<form> 
    <input type="file" id="files" name="files[]" multiple /> 
    <button type="button" id="run">Run</button> 
</form> 

<div id="preview"> 
    <output id="list"></output><br> 
    <output id="list2"></output><br> 
    <div id="status"></div> 
</div> 

Сценарий:

document.getElementById('files').addEventListener('change', handleFileSelect,false); 
    document.getElementById('run').addEventListener('click', read); 

    function handleFileSelect(evt) { 
     var files = evt.target.files; // FileList object 

     // Loop through the FileList and render image files as thumbnails. 
     for (var i = 0, f; f = files[i]; i++) { 

     // Only process image files. 
     if (!f.type.match('image.*')) { 
      continue; 
     } 

     var reader = new FileReader(); 

     // Closure to capture the file information. 
     reader.onload = (function(theFile) { 
      return function(e) { 
      // Render thumbnail. 
      var span = document.createElement('span'); 
      span.innerHTML = ['<img class="thumb" name="forms" src="', e.target.result, '" title="', escape(theFile.name), '"/ hidden>'].join(''); 
      document.getElementById('list').insertBefore(span, null); 
      var span = document.createElement('span'); 
      span.innerHTML = ['<canvas></canvas>'].join(''); 
      document.getElementById('list2').insertBefore(span, null);      
      }; 
     })(f); 
     // Read in the image file as a data URL. 
     reader.readAsDataURL(f); 
     } 
    } 

function read() { 
    imgs = document.getElementsByName('forms'); 
    canvas = document.getElementsByTagName("canvas"); 
    for (var i = 0; i < imgs.length; ++i) { 
     ctx[i] = canvas[i].getContext("2d"); 
     ctx[i].clearRect(0, 0, canvas[i].width, canvas[i].height); 
     preview.style.width = imgs[i].width + "px"; 
     preview.style.height = imgs[i].height + "px"; 
     canvas[i].width = imgs[i].width; 
     canvas[i].height = imgs[i].height;       
     ctx[i].drawImage(imgs[i], 0, 0, imgs[i].width, imgs[i].height); 
     // do all you need with each new canvas canvas 
    } 
} 
Смежные вопросы