通过javascript循环上传多个画布图像

时间:2015-02-11 15:26:21

标签: javascript php image canvas upload

我正在尝试制作一个上传脚本,在 saveimage.php 处理它们之前调整多个图像客户端的大小。原因是因为它们将被上传到可能存在非常慢的互联网的外部位置。

我已经能够在这里找到一些代码,这些代码帮我把它组合在一起。我只是一个初学者,所以它可能非常混乱!

它目前所做的是在“file_input”字段中输入文件时进行检查。然后它查看文件的数量并循环遍历它们,直到每个文件都放在画布中并上传到文件中。

然而,问题是:当我没有为每个文件添加警报时,循环过快,例如只处理10个图像中的1个或2个。因为上传脚本会比使用新图像更新画布更快。

这是我当前的页面,简化为核心:

<!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不是很有经验,所以如果有的话 更简单的方法来实现这一目标。请让我知道!

提前致谢!

4 个答案:

答案 0 :(得分:1)

JavaScript异步加载图像。这意味着一旦为其分配了新图像的.src,它就会开始加载图像,但会在图像需要时间加载的同时继续处理.src之后的javascript。

您在for循环中使用相同的图像变量(var img)。因此,每次循环时,您都会在上一个图像完全加载之前覆盖之前的img。

这是一个完全加载所有图像的图像加载器,然后调用start()函数来处理:

// 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[]

}

答案 1 :(得分:0)

在onload回调中,使用this关键字(而不是img)来获取当前图像,img可能/将在回调触发之前在for循环中被覆盖。<登记/> img.height --> this.height等 您是否还有使用自定义内容类型而不是application/x-www-form-urlencoded的原因? Url编码的表单数据更容易使用。

答案 2 :(得分:0)

我一直在努力解决同样的问题,但我终于来了 拼凑出另一个解决方案,使用其他人的代码来解决这个问题, 它的工作原理。它可能不完美,我欢迎任何改进建议。 这个概念是你有两个Javascript 函数,称为Resize0和Resize1,它们相互调用 直到所有照片都已调整大小,然后调整大小的功能 最后一张图片提交表格。两个函数之间传递参数 彼此以便其中一人知道何时提交表格。 其中两个参数是Number_Of_Images和当前Image_Number。 您还可以从中下载工作的示例网页 http://www.wantitconsulting.co.nz/ExampleResizeUpload.zip。 您需要在测试网站的基本目录中创建一个文件夹 为图像进入。 foldername是TestResizeUpload。服务器 方使用php。

答案 3 :(得分: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
    }
}
相关问题