[英]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">×
</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
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.