首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >多个图像上传JavaScript数组Stringify与大图像base64的斗争?

多个图像上传JavaScript数组Stringify与大图像base64的斗争?
EN

Stack Overflow用户
提问于 2018-10-16 07:40:02
回答 1查看 0关注 0票数 0

我正在尝试添加一个多图像上传器,它返回一个由用户选择图像填充的JavaScript数组。我将使用这个图像上传器与其他输入表单元素一起提交,在这种情况下,我不使用AJAX。最大文件上载大小为2MB。JavaScript数组包含base 64编码图像,其中包含大小,类型等所有细节。我使用了$('#j_son')。val(JSON.stringify(AttachmentArray)); 每次填充数组时,在数组外部填充隐藏的输入字段(输入unhidden以显示JSON字符串)。使用HTML5和客户端脚本进行缩略图预览的轻量级多文件上载

在此处输入图像描述
在此处输入图像描述

提交时,我将使用PHP解码新的JSON字符串,并将多个图像放在名为uploads的文件夹中。

我面临的问题是,选择大于200 KB的图像附件似乎会减慢div容器内图像的输出和隐藏输入字段内的JSON字符串,而任何大的内容都会导致chrome内部出现“aw snap”错误并导致崩溃浏览器,我不知道我哪里出错了。我还有一个点击事件,当用户单击X删除按钮并且隐藏的输入字段使用更新的JSON数组重新填充时,如果文件很大,这将非常慢并且崩溃。PHP方面解决JSON字符串没有问题,它似乎落在JavaScript代码或我在脚本底部添加的额外功能上。有没有办法阻止这种情况发生?我已经添加了完整的代码,包括PHP,如果有人想测试它。

代码语言:javascript
复制
<!DOCTYPE html> 
<html>
<head>
<title></title>
<meta charset="utf-8" />

<style>

    /*Copied from bootstrap to handle input file multiple*/
    .btn {
        display: inline-block;
        padding: 6px 12px;
        margin-bottom: 0;
        font-size: 14px;
        font-weight: normal;
        line-height: 1.42857143;
        text-align: center;
        white-space: nowrap;
        vertical-align: middle;
        cursor: pointer;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
        background-image: none;
        border: 1px solid transparent;
        border-radius: 4px;
    }
    /*Also */
    .btn-success {
        border: 1px solid #c5dbec;
        background: #D0E5F5;
        font-weight: bold;
        color: #2e6e9e;
    }
    /* This is copied from https://github.com/blueimp/jQuery-File- 
   Upload/blob/master/css/jquery.fileupload.css */
    .fileinput-button {
        position: relative;
        overflow: hidden;
    }

        .fileinput-button input {
            position: absolute;
            top: 0;
            right: 0;
            margin: 0;
            opacity: 0;
            -ms-filter: 'alpha(opacity=0)';
            font-size: 200px;
            direction: ltr;
            cursor: pointer;
        }

    .thumb {
        height: 80px;
        width: 100px;
        border: 1px solid #000;
    }

    ul.thumb-Images li {
        width: 120px;
        float: left;
        display: inline-block;
        vertical-align: top;
        height: 120px;
    }

    .img-wrap {
        position: relative;
        display: inline-block;
        font-size: 0;
    }

        .img-wrap .close {
            position: absolute;
            top: 2px;
            right: 2px;
            z-index: 100;
            background-color: #D0E5F5;
            padding: 5px 2px 2px;
            color: #000;
            font-weight: bolder;
            cursor: pointer;
            opacity: .5;
            font-size: 23px;
            line-height: 10px;
            border-radius: 50%;
        }

        .img-wrap:hover .close {
            opacity: 1;
            background-color: #ff0000;
        }

    .FileNameCaptionStyle {
        font-size: 12px;
    }
    </style>

    <script type="text/javascript" src="scripts/jquery-1.10.2.js"></script>
    <script type="text/javascript">

    //I added event handler for the file upload control to access the files 
    properties.
    document.addEventListener("DOMContentLoaded", init, false);

    //To save an array of attachments 
    var AttachmentArray = [];

    $('#j_son').val(JSON.stringify(AttachmentArray));

    //counter for attachment array
    var arrCounter = 0;

    //to make sure the error message for number of files will be shown only 
    one time.
    var filesCounterAlertStatus = false;

    //un ordered list to keep attachments thumbnails
    var ul = document.createElement('ul');
    ul.className = ("thumb-Images");
    ul.id = "imgList";

    function init() {
        //add javascript handlers for the file upload event
        document.querySelector('#files').addEventListener('change', 
    handleFileSelect, false);
    }

    //the handler for file upload event
    function handleFileSelect(e) {
        //to make sure the user select file/files
        if (!e.target.files) return;

        //To obtaine a File reference
        var files = e.target.files;

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

            //instantiate a FileReader object to read its contents into 
            memory
            var fileReader = new FileReader();

            // Closure to capture the file information and apply validation.
            fileReader.onload = (function (readerEvt) {
                return function (e) {

                    //Apply the validation rules for attachments upload
                    ApplyFileValidationRules(readerEvt)

                    //Render attachments thumbnails.
                    RenderThumbnail(e, readerEvt);

                    //Fill the array of attachment
                    FillAttachmentArray(e, readerEvt)
                };
            })(f);

            // Read in the image file as a data URL.
            // readAsDataURL: The result property will contain the 
            //file/blob's data encoded as a data URL.
            // More info about Data URI scheme 
            //https://en.wikipedia.org/wiki/Data_URI_scheme
            fileReader.readAsDataURL(f);
        }
        document.getElementById('files').addEventListener('change', 
    handleFileSelect, false);
    }

    //To remove attachment once user click on x button
    jQuery(function ($) {
        $('div').on('click', '.img-wrap .close', function () {
            var id = $(this).closest('.img-wrap').find('img').data('id');

            //to remove the deleted item from array
            var elementPos = AttachmentArray.map(function (x) { return 
            x.FileName; }).indexOf(id);
            if (elementPos !== -1) {
                AttachmentArray.splice(elementPos, 1);
            }

            //to remove image tag
            $(this).parent().find('img').not().remove();

            //to remove div tag that contain the image
            $(this).parent().find('div').not().remove();

            //to remove div tag that contain caption name
            $(this).parent().parent().find('div').not().remove();

            //to remove li tag
            var lis = document.querySelectorAll('#imgList li');
            for (var i = 0; li = lis[i]; i++) {
                if (li.innerHTML == "") {
                    li.parentNode.removeChild(li);
                }
            }

        });
    }
    )

    //Apply the validation rules for attachments upload
    function ApplyFileValidationRules(readerEvt)
    {
        //To check file type according to upload conditions
        if (CheckFileType(readerEvt.type) == false) {
            alert("The file (" + readerEvt.name + ") does not match the 
            upload conditions, You can only upload jpg/png/gif files");
            e.preventDefault();
            return;
        }

        //To check file Size according to upload conditions
        if (CheckFileSize(readerEvt.size) == false) {
            alert("The file (" + readerEvt.name + ") does not match the 
            upload conditions, The maximum file size for uploads should not 
            exceed 300 KB");
            e.preventDefault();
            return;
        }

        //To check files count according to upload conditions
        if (CheckFilesCount(AttachmentArray) == false) {
            if (!filesCounterAlertStatus) {
                filesCounterAlertStatus = true;
                alert("You have added more than 10 files. According to 
                upload conditions you can upload 10 files maximum");
            }
            e.preventDefault();
            return;
        }
    }

    //To check file type according to upload conditions
    function CheckFileType(fileType) {
        if (fileType == "image/jpeg") {
            return true;
        }
        else if (fileType == "image/png") {
            return true;
        }
        else if (fileType == "image/gif") {
            return true;
        }
         else if (fileType == "image/jpg") {
            return true;
        }
        else {
            return false;
        }
        return true;
    }

    //To check file Size according to upload conditions
    function CheckFileSize(fileSize) {
        if (fileSize < 2000000) {
            return true;
        }
        else {
            return false;
        }
        return true;
    }

    //To check files count according to upload conditions
    function CheckFilesCount(AttachmentArray) {
        //Since AttachmentArray.length return the next available index in 
        //the array, 
        //I have used the loop to get the real length
        var len = 0;
        for (var i = 0; i < AttachmentArray.length; i++) {
            if (AttachmentArray[i] !== undefined) {
                len++;
            }
        }
        //To check the length does not exceed 10 files maximum
        if (len > 9) {
            return false;
        }
        else
        {
            return true;
        }
    }

    //Render attachments thumbnails.
    function RenderThumbnail(e, readerEvt)
    {
        var li = document.createElement('li');
        ul.appendChild(li);
        li.innerHTML = ['<div class="img-wrap"> <span class="close">&times; 
        </span>' +
            '<img class="thumb" src="', e.target.result, '" title="', 
            escape(readerEvt.name), '" data-id="',
            readerEvt.name, '"/>' + '</div>'].join('');

        var div = document.createElement('div');
        div.className = "FileNameCaptionStyle";
        li.appendChild(div);
        div.innerHTML = [readerEvt.name].join('');
        document.getElementById('Filelist').insertBefore(ul, null);
    }

    //Fill the array of attachment
    function FillAttachmentArray(e, readerEvt)
    {
        AttachmentArray[arrCounter] =
        {
            AttachmentType: 1,
            ObjectType: 1,
            FileName: readerEvt.name,
            FileDescription: "Attachment",
            NoteText: "",
            MimeType: readerEvt.type,
            Content: e.target.result.split("base64,")[1],
            FileSizeInBytes: readerEvt.size,
        };
        arrCounter = arrCounter + 1;

        //THIS IS THE PART I ADDED TO POPULATE THE HIDDEN INPUT FIELD
        $('#j_son').val(JSON.stringify(AttachmentArray));
    }

    //THIS IS TO UPDATE THE INPUT FIELD WHEN A FILE IS REMOVED
    $(document).on('click', '.close', function(){
        var myString = JSON.stringify(AttachmentArray);
        $('#j_son').val(myString); 
    });


</script>

</head>
<body>
<div>
    <label style="font-size: 14px;">
        <span style='color:navy;font-weight:bold'>Attachment Instructions : 
</span>
    </label>

    <ul>
        <li>
            Allowed only files with extension (jpg, png, gif)
        </li>
        <li>
            Maximum number of allowed files 10 with 2 MB for each
        </li>
        <li>
            you can select files from different folders
        </li>
    </ul>
     <form method="POST" action="" enctype="multipart/form-data">
    <span class="btn btn-success fileinput-button">
        <span>Select Attachment</span>
        <input type="file" name="files[]" id="files" multiple 
        accept="image/jpeg, image/jpg image/png, image/gif,"><br />
    </span>

        <!--input field to be populated by the array-->
        <input type="text" name="j_son"  id="j_son" style="width: 500px;"> 

        <!--Submit and post to get decoded JSON string-->
        <button type="submit" id="image_post" name="post_it">Submit</button>

    </form>
    <output id="Filelist"></output>

</div>


<?php 

if(isset($_POST['post_it']))
{
    //other input fields

    $file = $_POST['j_son'];

    $tempData = html_entity_decode($file);
    $cleanData = json_decode($tempData, true);

    foreach($cleanData as $p)
    {
        echo $p['Content']."</br>";

        //insert code to uploads folder
    }
}
?>
</body>
</html>
EN

回答 1

Stack Overflow用户

发布于 2018-10-16 16:56:00

- 编辑 -

这可能是因为chrome中的已知问题。尝试使用本文中推荐的blob

javascript如何上传blob?

代码语言:javascript
复制
function uploadAudio( blob ) {
  var reader = new FileReader();
  reader.onload = function(event){
    var fd = {};
    fd["fname"] = "test.wav";
    fd["data"] = event.target.result;
    $.ajax({
      type: 'POST',
      url: 'upload.php',
      data: fd,
      dataType: 'text'
    }).done(function(data) {
        console.log(data);
    });
  };
  reader.readAsDataURL(blob);
}

- /编辑 -

好吧,好像你正在多次向“files”id添加一个onChange事件监听器。一旦进入init,每次调用handleFileSelect函数一次。这肯定是你的减速问题。

此外,如果您要将文件上载大小最大为2MB,则应使用upload_max_filesize在PHP文件中设置此值,并设置post_max_size。

代码语言:javascript
复制
ini_set('upload_max_filesize', '2M');
ini_set('post_max_size', '2M');

来自php.net:

的upload_max_filesize 上传文件的最大大小。 的post_max_size 设置允许的后期数据的最大大小。此设置也会影响文件上载。要上传大文件,此值必须大于upload_max_filesize。一般来说,memory_limit应该大于post_max_size。使用整数时,该值以字节为单位。

此外,如果您的上传结束超时,您可能还希望通过使用max_input_time或max_execution时间来延长执行时间,尽管我认为max_input_time应该足够了。

ini_set('max_input_time',300); ini_set('max_execution_time',300);

max_input_time设置 这将设置允许脚本解析输入数据的最长时间(以秒为单位),如POST和GET。定时从服务器上调用PHP开始,到执行开始时结束。默认设置为-1,表示使用max_execution_time。设置为0以允许无限时间。 的max_execution_time 这将设置允许脚本在解析器终止之前运行的最长时间(以秒为单位)。这有助于防止写得不好的脚本占用服务器。默认设置为30.从命令行运行PHP时,默认设置为0。

这需要在其他输出之前添加到PHP文件的顶部。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100005073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档