拖放上传图片 - 支持API问题

时间:2013-08-19 14:16:12

标签: html5 file-upload drag-and-drop xmlhttprequest

我正在使用此tutorial作为指导来实现我自己的HTML5 drag'n'drop -upload功能。

我还使用File API,FileReader API和XHR2 API

我还将this源代码中的代码段添加到我的代码中,以检查API支持。

奇怪的是我用Chrome 28.0.1和Firefox 23.0.1打开文件,实际上支持XHR2和File API,我得到了

File API & FileReader API not supported

XHR2's FormData is not supported

XHR2's upload progress isn't supported

我不明白出了什么问题。我是这些API的新手。发生语法错误是一回事,但API不支持?它们应该在哪里?我只是不明白。

感谢您的时间

这是我的代码

    <style>
    #holder { border: 10px dashed #ccc; width: 300px; min-height: 300px; margin: 20px auto;}
    #holder.hover { border: 10px dashed #0c0; }
    #holder img { display: block; margin: 10px auto; }
    #holder p { margin: 10px; font-size: 14px; }
    progress { width: 100%; }
    progress:after { content: '%'; }
    .fail { background: #c00; padding: 2px; color: #fff; }
    .hidden { display: none !important;}
    </style>


    <script type='text/javascript'>
//check for support API
    var holder = document.getElementById('holder'),
         tests = {
          filereader: typeof FileReader != 'undefined',
          dnd: 'draggable' in document.createElement('span'),
          formdata: !!window.FormData,
          progress: "upload" in new XMLHttpRequest
        }, 
        support = {
          filereader: document.getElementById('filereader'),
          formdata: document.getElementById('formdata'),
          progress: document.getElementById('progress')
        },
        acceptedTypes = {
          'image/png': true,
          'image/jpeg': true,
          'image/gif': true
        },
        progress = document.getElementById('uploadprogress'),
        fileupload = document.getElementById('upload');

    "filereader formdata progress".split(' ').forEach(function (api) {
      if (tests[api] === false) {
          alert('inside me, bad...');
        support[api].className = 'fail';
      } else {
        // FFS. I could have done el.hidden = true, but IE doesn't support
        // hidden, so I tried to create a polyfill that would extend the
        // Element.prototype, but then IE10 doesn't even give me access
        // to the Element object. Brilliant.
        support[api].className = 'hidden';
      }
    });

//preview files/images-give feedback to user
    function previewfile(file) {
      if (tests.filereader === true && acceptedTypes[file.type] === true) {
        var reader = new FileReader();
        reader.onload = function (event) {
          var image = new Image();
          image.src = event.target.result;
          image.width = 250; // a fake resize
          holder.appendChild(image);
        };

        reader.readAsDataURL(file);
      }  else {
        holder.innerHTML += '<p>Uploaded ' + file.name + ' ' + (file.size ? (file.size/1024|0) + 'K' : '');
        alert(file.name);
        console.log(file);
      }
    }

    //read file from drop area
    function readfiles(files) {
        debugger;
        var formData = tests.formdata ? new FormData() : null;
        for (var i = 0; i < files.length; i++) {
          if (tests.formdata) formData.append('file', files[i]);
          alert(files[i].name);
          previewfile(files[i]);
        }

        // now send file
        if (tests.formdata) {
          var xhr = new XMLHttpRequest();
          xhr.open('POST', '/upload.php');
          xhr.onload = function() {
            progress.value = progress.innerHTML = 100;
          };

          if (tests.progress) {
            xhr.upload.onprogress = function (event) {
              if (event.lengthComputable) {
                var complete = (event.loaded / event.total * 100 | 0);
                progress.value = progress.innerHTML = complete;
              }
            }
          }

          xhr.send(formData);
        }
    }

    if (tests.dnd) { 

       holder.addEventListener('drop', ondrop, false); 
       holder.addEventListener('dragover', ondragover, false); 
       holder.addEventListener('dragend', ondragend, false); 

      holder.ondragover = function () { this.className = 'hover'; return false; };
      holder.ondragend = function () { this.className = ''; return false; };
      holder.ondrop = function (e) {
        this.className = '';
        e.preventDefault();
        readfiles(e.dataTransfer.files);
      }
    } else {
      fileupload.className = 'hidden';
      fileupload.querySelector('input').onchange = function () {
        readfiles(this.files);
      };
    }

    </script>


    <!-- the html -->
     <div id="holder">
      </div> 

      <p id="upload" class="hidden"><label>Drag &amp; drop not supported, but you can still upload via this input field:<br><input type="file"></label></p>
      <p id="filereader">File API &amp; FileReader API not supported</p>
      <p id="formdata">XHR2's FormData is not supported</p>
      <p id="progress">XHR2's upload progress isn't supported</p>
      <p>Upload progress: <progress id="uploadprogress" min="0" max="100" value="0">0</progress></p>
      <p>Drag an image from your desktop on to the drop zone above to see the browser both render the preview, but also upload automatically to this server.</p>

1 个答案:

答案 0 :(得分:3)

<强>问题

基本上,javascript正在尝试访问尚不存在的html。

<强>解决方案

这可以通过在加载html后运行javascript来解决。

有很多方法可以做到这一点:

  • 将javascript放入脚本标记并放在html下。
  • 将javascript放入其自己的文件中,并将此(<script type="text/javascript" src="script.js"></script>)放在html下。
  • 将javascript放入函数中,然后将onload="functionName();"添加到body标记。
  • 使用jQuery仅在文档“准备就绪”时运行代码,例如$(document).ready(function () { //code goes here });
  • 我们还没有真正需要进入的许多其他方式。

让我们测试一下以确保

您提供的代码会出现此错误TypeError: support[api] is null on line 44

为了进行快速测试,我在第44行上方添加了console.log('api',api);

所以44号线&amp; 45看起来像这样:

console.log('api',api);
support[api].className = 'hidden';

控制台日志输出:

api filereader
TypeError: support[api] is null

再看一下代码,我们可以看到第23行设置了support[filereader]

support = {
          filereader: document.getElementById('filereader'),

所以api = document.getElementById('filereader'),恰好是null。这意味着javascript无法找到id =“filereader”的任何元素。

但我们知道它存在于第126行

<p id="filereader">File API &amp; FileReader API not supported</p>

所以也许javascript无法访问它,因为它已经加载到页面上了。

让我们尝试将javascript放在html下面...现在它可以正常工作!

希望这会有所帮助: - )