簡體   English   中英

多個圖像上傳JavaScript數組Stringify與大型圖像作斗爭base64

[英]Multiple image upload JavaScript array Stringify struggles with large images base64

我正在嘗試添加一個多圖像上載器,該上載器返回一個JavaScript數組,該數組由用戶選擇圖像填充。 我將使用此圖像上載器以及其他所有將一起提交的輸入表單元素,在這種情況下,我不使用AJAX。 文件最大上傳大小為2MB。 JavaScript數組包含基本64位編碼的圖像,其中包括大小,類型等所有詳細信息。我使用了$('#j_son')。val(JSON.stringify(AttachmentArray)); 每次在數組外部填充數組時都會填充隱藏的輸入字段(取消隱藏輸入以顯示JSON字符串)。 使用HTML5和客戶端腳本通過縮略圖預覽進行輕量級多文件上傳

在此處輸入圖片說明

提交后,我將使用PHP解碼新的JSON字符串,並將多個圖像放入一個名為uploads的文件夾中。

我面臨的問題是,選擇大於200 KB的圖像附件似乎會減慢div容器內圖像的輸出以及隱藏輸入字段內的JSON字符串的速度,任何較大的操作都會導致chrome內的“ aw snap”錯誤並導致崩潰瀏覽器,我不知道哪里出了問題。 我還有一個click事件,當用戶單擊X remove按鈕,並且用更新的JSON數組重新填充隱藏的輸入字段時,這確實很慢,並且如果文件很大,則會崩潰。 PHP方面對解碼JSON字符串沒有問題,它似乎屬於JavaScript代碼或我在腳本底部添加的額外功能。 有沒有辦法阻止這種情況的發生? 如果有人要測試它,我已經添加了完整的代碼,包括PHP。

<!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>

-編輯-

這可能是由於chrome中的一個已知問題。 嘗試按照本文中的建議使用Blob

javascript如何上傳Blob?

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);
}

-/編輯-

好的,好像您要向“文件” ID多次添加onChange事件偵聽器。 一次初始化,每次調用handleFileSelect函數。 這肯定是您的減速問題。

另外,如果文件上傳大小最大為2MB,則應在PHP文件中使用upload_max_filesize進行設置,並設置post_max_size。

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 time來延長執行時間,盡管我認為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文件的頂部。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM