javascript - 上传大约 150 张照片后浏览器崩溃

标签 javascript performance browser html5-canvas jquery-file-upload

我正在开发一个应用程序,我们使用 jquery fileupload 上传大约 200-300 张图像。在上传之前,我需要在浏览器中使用 Canvas 调整其大小以减少服务器负载。 但在上传大约 150 张照片并收到错误后,页面崩溃了 哇咔咔!平滑出错

这是我用来调整文件大小和上传文件的 JavaScript 代码,

<script>
$(document).ready(function(){

  function formatBytes(bytes, decimals = 2) {
    if (bytes === 0) return '0 Bytes';

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
  }


  /* Utility function to convert a canvas to a BLOB */
  var dataURLToBlob = function(dataURL) {
    var BASE64_MARKER = ';base64,';
    if (dataURL.indexOf(BASE64_MARKER) == -1) {
      var parts = dataURL.split(',');
      var contentType = parts[0].split(':')[1];
      var raw = parts[1];

      return new Blob([raw], {type: contentType});
    }

    var parts = dataURL.split(BASE64_MARKER);
    var contentType = parts[0].split(':')[1];
    var raw = window.atob(parts[1]);
    var rawLength = raw.length;

    var uInt8Array = new Uint8Array(rawLength);

    for (var i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }

    return new Blob([uInt8Array], {type: contentType});
  }
  /* End Utility function to convert a canvas to a BLOB      */

  $("#fileupload").change(function(e){
    e.preventDefault();
    $('.loader_image, .loader_text').removeClass('hide');
    for (var i = 0; i < this.files.length; i++){
      var file = this.files[i];
      var reader = new FileReader();
      reader.onload = function (readerEvent) {
        var image = new Image();
        image.onload = function (imageEvent) {

          // Resize the image
          var canvas = document.createElement('canvas'),
            max_size = 1600,// TODO : pull max size from a site config
            width = image.width,
            height = image.height;
          if (width > height) {
            if (width > max_size) {
              height *= max_size / width;
              width = max_size;
            }
          } else {
            if (height > max_size) {
              width *= max_size / height;
              height = max_size;
            }
          }
          canvas.width = width;
          canvas.height = height;
          canvas.getContext('2d').drawImage(image, 0, 0, width, height);
          var mimeType = image.src.match(/[^:]\w+\/[\w-+\d.]+(?=;|,)/)[0];
          var ext = image.src.match(/[^:/]\w+(?=;|,)/)[0];
          var dataUrl = canvas.toDataURL(mimeType);
          var resizedImage = dataURLToBlob(dataUrl);

          image_html = '<div class="col-sm-2 sm-margin-bottom-30 image_subcontainer" style="margin-bottom: 20px;" data-filename="'+imageEvent.target.name+'"><p class="album-btn" align="right" style=""><a class="remove_photo" role="button" style="color:grey;" rel="nofollow" href="#">&nbsp;</a></p><p></p><a href="#" class="fancybox img-hover-v1"><span style="height: 140px; padding-top: 14px;"><img src="'+image.src+'"></span></a><div style="text-align: center;margin-bottom: 30px;">'+imageEvent.target.name+'</div> <div id="progress" class="col-sm-2 sm-margin-bottom-27" style="padding-bottom: 10px;"><div class="bar" style="width: 0%;"></div><span class="data_loaded"></span></div></div>'

          $('.images_fancybox').prepend(image_html);
          $('#fileupload').fileupload('add', {files: [new File([resizedImage], imageEvent.target.name)]})
        }
        image.name = readerEvent.target.fileName;
        image.src = readerEvent.target.result;
      }
      reader.fileName = file.name;
      reader.readAsDataURL(file);
    }

  });


  $('#fileupload').fileupload({
    dataType: 'json',
    add: function (e, data) {
      var fileType = data.files[0].name.split('.').pop().toLowerCase(), allowdtypes = 'jpeg,jpg,png';
      if (allowdtypes.indexOf(fileType) < 0) {
        alert('Invalid file type '+fileType+'. Allowed file types: jpeg,jpg,png ');
        return false;
      }
      if(data.fileInput == undefined){
        data.submit()
      }
      // console.log(data);
    },
    start: function (e) {
      // progressBar = '<div id="progress" class="col-sm-2 sm-margin-bottom-30"><div class="bar progress-bar-warning" style="width: 0%;"></div></div>'
      // $('#progress_bar').append(progressBar);
    },
    progressall: function (e, data) {
      if(data.loaded == data.total){
        $('.loader_image, .loader_text').addClass('hide');
      }
    },
    progress: function (e, data) {

      var progress = parseInt(data.loaded / data.total * 100, 10);
      $('div[data-filename="'+data.files[0].name+'"] #progress .bar, div[data-filename="'+data.files[0].name+'"] #progress').css(
        'width',
        progress + '%'
      );

      $('div[data-filename="'+data.files[0].name+'"] #progress .data_loaded').text(formatBytes(data.loaded) + "/" + formatBytes(data.total))

    },
    done: function (e, data) {
      if(data.result.success){
        var uploaded_image = imageContainer(data.result.id, data.result.album_id, data.result.filename, data.result.fileurl, data.result.authenticity_token)
        // $('div[data-filename="'+data.result.filename+'"]').remove();
        // $('.images_fancybox').prepend(uploaded_image);
        $('div[data-filename="'+data.files[0].name+'"]').replaceWith(uploaded_image);
        SP.Photo.bindEvents();
        SP.Photo.initNoteForm();
        SP.App.initFancybox();
      }else{
        $('.container_wrapper .flash_messages').html(data.result.error_html)
      }
    },
    fail: function(e, data){
      console.log(data);
    },
    always: function(e, data){
      console.log(data);
    },
  });


  function imageContainer(id, album_id, filename, fileurl, authenticity_token){
    return '<div class="col-sm-2 sm-margin-bottom-30 image_subcontainer" data-photo-id="'+id+'" style="margin-bottom: 20px;"><p class="album-btn" align="right" style=""><a data-toggle="tooltip" data-placement="top" data-original-title="Delete photo" class="remove_photo tooltips glyphicon glyphicon-remove" role="button" data-confirm="Your are attemtping to delete a photo. Press "Ok" to delete or "Cancel" to cancel the request." style="color:grey;" data-remote="true" rel="nofollow" data-method="delete" href="/photographer/albums/'+album_id+'/photos/'+id+'"></a><a data-id="'+id+'" class="add_note_btn add_note_'+id+' pull-left glyphicon glyphicon-edit " style="color:grey;" href="#" data-original-title="" title=""></a></p><div style="display: none;" class="add_note_class_'+id+'"><div class="row"><div class="col-sm-12"><form class="note_form" data-id="'+id+'" id="edit_photo_'+id+'" action="/photographer/albums/'+album_id+'/photos/'+id+'" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="_method" value="put"><input type="hidden" name="authenticity_token" value="'+authenticity_token+'"><fieldset><div id="status-area" data-id="'+id+'"></div><div class="row"><section class="col col-12"><textarea rows="3" style="resize:vertical;" class="form-control note_input_'+id+'" name="photo[photographer_note]" id="photo_photographer_note"></textarea></section></div></fieldset><br><fieldset><div class="row"><img class="loader_image hide pull-left" src="/assets/loader.gif" alt="Loader" width="30" height="30"><input type="submit" name="commit" value="Submit" class="btn btn-info pull-right" data-disable-with="Submit"></div></fieldset></form></div><div class="row"><div class="col-sm-12"></div></div><div class="row"><div class="col-sm-12"></div></div></div></div><p></p><a href="'+fileurl+'" data-fancybox="gallery" data-caption="'+filename+'" class="fancybox img-hover-v1" title="'+filename+'" id="'+id+'" data-user="suggested" data-album-id="'+album_id+'"><span style="height: 140px; padding-top: 14px;"><img class="img-responsive" src="'+fileurl+'"></span></a><!-- word-wrap: break-word; --><div style="text-align: center;">'+filename+'</div><div style="padding-bottom: 30px;"><a data-id="suggested_'+id+'" class="suggested_'+id+'" data-remote="true" href="/photographer/albums/'+album_id+'/photos/'+id+'/suggest"><button type="button" class=" btn-warning pull-left btn-circle"><i class="glyphicon "></i></button></a><a href="#"><button type="button" class=" btn-success pull-right btn-circle"><i class="glyphicon "></i></button></a></div></div>'
  }
});
</script>

最佳答案

我自己解决了这个问题。问题出在 FileReader 上。 这需要清除文件读取器。因此,通过添加以下内容可以解决我的问题。

reader.onloadend = function(image) {
  image.src= '';
}

关于javascript - 上传大约 150 张照片后浏览器崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58659072/

相关文章:

javascript - 在 PerformanceTiming 中,AJAX 请求时间对流程模型的哪一部分有贡献?

html - 溢出-x :hidden not working on iPhone

python - 如何禁用 python 中的 webbrowser 消息?

相当于Scrapy的Javascript框架

javascript - Meteor:如何将项目推送到用户集合并创建列表或数组,而不是用新项目替换每个项目?

php - 如何处理从一个客户端到一个 PHP 脚本的多个并行请求

performance - 为顺序访问优化磁盘数据的位置

html - 溢出 : hidden does not work in Chrome

javascript - Mysql选择包含字符串+特定int列的行比较

javascript - 具有相同名称的多个单选按钮组