【问题标题】:Upload multiple canvas images through javascript loop通过javascript循环上传多个画布图像
【发布时间】:2015-04-12 01:01:13
【问题描述】:

我正在尝试制作一个上传脚本,在 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 不是很有经验,所以如果有 实现这一目标的简单得多的方法。请告诉我!

提前致谢!

【问题讨论】:

  • 在做任何其他事情之前:设置 onload 处理程序 before 设置 src。
  • @GameAlchemist 我现在把 onload 处理程序放在了 src 之前,它似乎仍然以同样的方式运行,这是什么原因?

标签: javascript php image canvas upload


【解决方案1】:

在 onload 回调中使用 this 关键字(而不是 img)来处理当前图像,img 可能/将在回调触发之前在 for 循环中被覆盖。
img.height --&gt; this.height
还有你使用自定义内容类型而不是application/x-www-form-urlencoded 的原因吗?
Url 编码的表单数据更易于使用。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2021-11-02
        • 1970-01-01
        • 2018-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-30
        • 1970-01-01
        相关资源
        最近更新 更多