关于html5:10个有用的HTML文件上传技巧

6次阅读

共计 11360 个字符,预计需要花费 29 分钟才能阅读完成。

上传文件的能力是许多 Web 和挪动利用的要害需要,从将照片上传到社交媒体上到将简历公布到工作门户网站上,文件上传无处不在。

作为一名 Web 开发人员,咱们肯定晓得 HTML 提供了原生文件上传的反对,并借助于 JavaScript 的一点帮忙。在 HTML5 中,File API 被增加到 DOM 中。利用它,咱们能够读取 FileList 和其中的 File 对象,这就解决了文件的多种用例,即在本地加载文件或通过网络发送到服务器进行解决等。

在本文中,咱们将探讨 HTML 文件上传反对的 10 种用法,心愿你感觉它有用。

在任何时候,如果您想应用这些文件上传性能,都能够在这里找到:

HTML 文件上传演示:https://html-file-upload.netl…

该演示的源代码在我的 Github 存储库中,✋请随时关注我,并通过示例不断更新代码,如果您感觉有用,请给一个⭐。

源代码仓库:https://github.com/atapas/htm…

1. 单个文件上传

咱们能够将输出类型指定为 file,以在 Web 应用程序中应用文件上传器性能。

<input type="file" id="file-uploader">

输出文件类型使用户能够通过按钮上传一个或多个文件,默认状况下,它容许应用操作系统的本地文件浏览器上传单个文件。

上传胜利后,File API 能够应用简略的 JavaScript 代码读取 File 对象。要读取 File 对象,咱们须要监听文件上传器的 change 事件。

首先,通过 ID 获取文件上传器实例

const fileUploader = document.getElementById('file-uploader');

而后增加一个 change 事件侦听器,以在上传实现后读取文件对象,咱们从 event.target.files 属性获取上传的文件信息。

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  console.log('files', files);
});

在浏览器控制台中察看输入,留神 FileList 数组中的 File 对象领有上传文件的所有元数据信息。

上面是雷同示例的代码页,供您进一步钻研

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1> 单个文件上传 </h1>
  <input type="file" id="file-uploader">
  <p> 上传文件,并在浏览器控制台中查看输入。</p>
  <p id="feedback"></p>
</div>
const fileUploader = document.getElementById('file-uploader');

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  console.log('files', files);
  
  const feedback = document.getElementById('feedback');
  const msg = `File ${files[0].name} uploaded successfully!`;
  feedback.innerHTML = msg;
});

2. 多文件上传

咱们能够一次上传多个文件。为此,咱们只须要在输出文件标签中增加一个名为 multiple 的属性即可。

<input type="file" id="file-uploader" multiple />

当初,文件浏览器将容许您上传一个或多个要上传的文件。就像后面的例子一样,你能够增加一个 change 事件处理程序来捕捉上传文件的信息。您是否留神到 FileList 是一个数组?对,对于多个文件上传,数组将具备以下信息:

上面是 CodePen 链接,用于摸索多个文件上传。

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1> 多文件上传 </h1>
  <input type="file" id="file-uploader" multiple>
  <p> 上传多个文件并在浏览器控制台中查看输入 </p>
  <p id="feedback"></p>
</div>
const fileUploader = document.getElementById('file-uploader');

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  console.log('files', files);
  
  // show the upload feedback
  const feedback = document.getElementById('feedback');
  const msg = `${files.length} file(s) uploaded successfully!`;
            feedback.innerHTML = msg;
});

3. 理解文件元数据

每当咱们上传一个文件时,File 对象都有元数据信息,如文件名、大小、最初更新工夫、类型等,此信息对于进一步的验证和决策很有用。

// 通过 id 获取文件上传者
const fileUploader = document.getElementById('file-uploader');

// 监听 change 事件并读取元数据
fileUploader.addEventListener('change', (event) => {
  // 获取 FileList 数组
  const files = event.target.files;

  // 循环浏览文件并获取元数据
  for (const file of files) {
    const name = file.name;
    const type = file.type ? file.type: 'NA';
    const size = file.size;
    const lastModified = file.lastModified;
    console.log({file, name, type, size, lastModified});
  }
});

这是单个文件上传的输入:

应用此 CodePen 进行进一步摸索

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1>Read File Metadata</h1>
  <input type="file" id="file-uploader">
  <p id="feedback"></p>
</div>
const fileUploader = document.getElementById('file-uploader');

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  console.log('files', files);
  
  for (const file of files) {
    const name = file.name;
    const type = file.type ? file.type : 'NA';
    const size = file.size;
    const lastModified = file.lastModified;
    console.log({file, name, type, size, lastModified});
    
    const feedback = document.getElementById('feedback');
    const msg = ` File Name: ${name} <br/>
              File Size: ${size} <br/>
              File type: ${type} <br/>
              File Last Modified: ${new Date(lastModified)}`;
              
    feedback.innerHTML = msg;
  }
});

4. 理解文件 accept 属性

咱们能够应用 accept 属性来限度要上传的文件的类型,您可能心愿在用户上传个人资料图片时,只显示容许浏览 png 格局图片类型。

<input type="file" id="file-uploader" accept=".jpg, .png" multiple>

在下面的代码中,文件浏览器将只容许扩大名为 jpgpng 的文件。

请留神,在这种状况下,文件浏览器会主动将文件抉择类型设置为自定义而不是全副。然而,如果须要,您始终能够将其更改回所有文件。

应用此 CodePen 摸索 accept 属性

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1> 只能抉择.png 和.jpg 文件 </h1>
  <input type="file" id="file-uploader" accept=".jpg, .png" multiple>
  <p>Upload files and see the output in browser console</p>
</div>
const fileUploader = document.getElementById('file-uploader');

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  console.log('files', files);
});

5. 管理文件内容

您能够在胜利上传文件后显示文件内容。对于个人资料图片,如果上传后不立刻向用户展现上传的图片,会造成凌乱。

咱们能够应用 FileReader 对象将文件转换为二进制字符串。而后增加 load 事件侦听器,以在胜利上传文件时获取二进制字符串。

// 获取 FileReader 的实例
const reader = new FileReader();

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  const file = files[0];

  // 上传后获取文件对象并读取
  // 数据作为 URL 二进制字符串
  reader.readAsDataURL(file);

  // 加载后,对字符串进行解决
  reader.addEventListener('load', (event) => {
    // 在这里咱们创立一个图像标签并增加图片
    const img = document.createElement('img');
    imageGrid.appendChild(img);
    img.src = event.target.result;
    img.alt = file.name;
  });
});

尝试在上面的 CodePen 中抉择一个图像文件,而后查看其渲染。

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1> 显示文件内容 </h1>
  <input type="file" id="file-uploader" accept=".jpg, .jpeg, .png" >
  <div id="image-grid"></div>
</div>
const fileUploader = document.getElementById('file-uploader');
const reader = new FileReader();
const imageGrid = document.getElementById('image-grid');

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  const file = files[0];
  reader.readAsDataURL(file);
  
  reader.addEventListener('load', (event) => {const img = document.createElement('img');
    imageGrid.appendChild(img);
    img.src = event.target.result;
    img.alt = file.name;
  });
});

6. 验证文件大小

如咱们所见,咱们能够读取文件的大小元数据,实际上能够将其用于文件大小验证,您可能容许用户上传最大 1MB 的图像文件。让咱们看看如何实现这一指标。

// 文件上传 change 事件的侦听器
fileUploader.addEventListener('change', (event) => {
  // 读取文件大小
  const file = event.target.files[0];
  const size = file.size;

  let msg = '';

 // 查看文件大小是否大于 1MB,并筹备一条音讯。if (size > 1024 * 1024) {msg = `<span style="color:red;">The allowed file size is 1MB. The file you are trying to upload is of ${returnFileSize(size)}</span>`;
  } else {msg = `<span style="color:green;"> A ${returnFileSize(size)} file has been uploaded successfully. </span>`;
  }

  // 向用户显示音讯
  feedback.innerHTML = msg;
});

尝试上传不同大小的文件,以查看验证的工作原理

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1> 查看文件大小 </h1>
  <input type="file" id="file-uploader">
  
  <div id="feedback"></div  
</div>
const fileUploader = document.getElementById('file-uploader');
const feedback = document.getElementById('feedback');

fileUploader.addEventListener('change', (event) => {const file = event.target.files[0];
  console.log('file', file);
  
  const size = file.size;
  console.log('size', size);
  let msg = '';
  
  if (size > 1024 * 1024) {msg = `<span style="color:red;">The allowed file size is 1MB. The file you are trying to upload is of ${returnFileSize(size)}</span>`;
  } else {msg = `<span style="color:green;"> A ${returnFileSize(size)} file has been uploaded successfully. </span>`;
  }
  feedback.innerHTML = msg;
});

function returnFileSize(number) {if(number < 1024) {return number + 'bytes';} else if(number >= 1024 && number < 1048576) {return (number/1024).toFixed(2) + 'KB';
  } else if(number >= 1048576) {return (number/1048576).toFixed(2) + 'MB';
  }
}

7. 显示文件上传进度

更好的可用性是让你的用户晓得文件上传的过程。当初,咱们晓得了 FileReader 和读取和加载文件的事件。

const reader = new FileReader();

FileReader 有另一个事件,称为进度 (progress),晓得已加载了多少。咱们能够应用 HTML5 的 progress 标签来创立带有此信息的进度栏。

reader.addEventListener('progress', (event) => {if (event.loaded && event.total) {
    // 计算实现百分比
    const percent = (event.loaded / event.total) * 100;
    // 将值设置为进度组件
    progress.value = percent;
  }
});

不如你试着上传一个大一点的文件,看看上面的 CodePen 中的进度条工作状况如何?试试吧。

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1>File upload progress</h1>
  <input type="file" id="file-uploader">
  
  <div id="feedback"></div>
  
  <label id="progress-label" for="progress"></label>
  <progress id="progress" value="0" max="100"> </progress>
</div>
const fileUploader = document.getElementById('file-uploader');
const feedback = document.getElementById('feedback');
const progress = document.getElementById('progress');

const reader = new FileReader();

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  const file = files[0];
  reader.readAsDataURL(file);
  
  reader.addEventListener('progress', (event) => {if (event.loaded && event.total) {const percent = (event.loaded / event.total) * 100;
      progress.value = percent;
      document.getElementById('progress-label').innerHTML = Math.round(percent) + '%';
      
      if (percent === 100) {let msg = `<span style="color:green;">File <u><b>${file.name}</b></u> has been uploaded successfully.</span>`;
        feedback.innerHTML = msg;
      }
    }
  });
});

8. 目录上传呢?

咱们能够上传整个目录吗?好吧,这是可能的,但有一些限度。有一个叫做 webkitdirectory 的非标准属性(至多在写这篇文章的时候是这样),容许咱们上传整个目录。

尽管最后只针对基于 WebKit 的浏览器实现,但 webkitdirectory 也能够在 Microsoft Edge 以及 Firefox 50 和更高版本中应用。然而,即便它具备绝对宽泛的反对,它依然不是规范的,除非您别无选择,否则不应该应用它。

您能够将此属性指定为

<input type="file" id="file-uploader" webkitdirectory />

这将容许您抉择一个文件夹(又名目录)

用户必须提供确认信息能力上传目录,

用户单击“Upload”按钮后,就会进行上传。这里要留神的重要一点:FileList 数组将以立体构造的模式蕴含无关上载目录中所有文件的信息。但要害是,对于每个 File 对象,webkitRelativePath 属性都会有目录门路。

例如,让咱们思考一个 main 目录及其下的其余文件夹和文件,

当初,File 对象将将 webkitRelativePath 填充为

您能够应用它在您抉择的任何 UI 构造中出现文件夹和文件。应用此 CodePen 进行进一步摸索。

CodePen:https://codepen.io/atapas/pen…

<div>
  <h1>Upload directories</h1>
  <input type="file" id="file-uploader" webkitdirectory />
  
  <ul id="pathList"></ul>
</div>
const fileUploader = document.getElementById('file-uploader');
const pathList = document.getElementById('pathList');

function removeAllChildNodes(parent) {while (parent.firstChild) {parent.removeChild(parent.firstChild);
    }
}

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  console.log('files', files);
  
  removeAllChildNodes(pathList);
  
  [...files].forEach((file, index) => {let path = document.createElement('li');
    path.innerHTML = file.webkitRelativePath;
    pathList.appendChild(path);
  });
});

9. 让咱们拖放,上传

不反对拖放性能进行文件上传是一种古老的形式,不是吗?让咱们看看如何通过几个简略的步骤来实现这一指标。

首先,创立一个搁置区和一个可选的区域以显示上传的文件内容。咱们将应用图像作为文件拖放到此处。

<div id="container">
  <h1>Drag & Drop an Image</h1>
  <div id="drop-zone">
    DROP HERE
  </div>

  <div id="content">
    Your image to appear here..
  </div>
</div>

通过它们各自的 ID 获取拖拽和内容区域。

const dropZone = document.getElementById('drop-zone');
const content = document.getElementById('content');

增加一个 dragover 事件处理程序,以显示将要复制的内容的成果,

dropZone.addEventListener('dragover', event => {event.stopPropagation();
  event.preventDefault();
  event.dataTransfer.dropEffect = 'copy';
});

接下来,定义搁置图像时咱们要做什么,咱们将须要一个 drop 事件监听器来解决。

dropZone.addEventListener('drop', event => {
  // 获取文件
  const files = event.dataTransfer.files;

    // 当初,咱们能够尽所有可能来展现文件内容在一个 HTML 元素中,如,DIV。});

尝试在上面的 CodePen 示例中拖放图像文件,并查看其工作原理,不要遗记查看代码以渲染拖放的图像。

CodePen:https://codepen.io/atapas/pen…

<div id="container">
  <h1>Drag & Drop an Image</h1>
  <div id="drop-zone"> DROP HERE </div>
  <div id="content">Your image to appear here.. </div>
</div>
const dropZone = document.getElementById('drop-zone');
const content = document.getElementById('content');

const reader = new FileReader();

if (window.FileList && window.File) {
  dropZone.addEventListener('dragover', event => {event.stopPropagation();
    event.preventDefault();
    event.dataTransfer.dropEffect = 'copy';
  });
  
  dropZone.addEventListener('drop', event => {
    content.innerHTML = '';
    event.stopPropagation();
    event.preventDefault();
    const files = event.dataTransfer.files;
    console.log(files);
    
    reader.readAsDataURL(files[0]);
  
    reader.addEventListener('load', (event) => {
      content.innerHTML = '';
      const img = document.createElement('img');
      img.style.height = '400px';
      img.style.width = '400px';
      content.appendChild(img);
      img.src = event.target.result;
      img.alt = file.name;
      
    });
  }); 
}

10. 应用 objectURLs 解决文件

有一个称为 URL.createObjectURL() 的非凡办法,能够从文件创建惟一的 URL,您也能够应用 URL.revokeObjectURL() 办法开释它。

DOM URL.createObjectURL()URL.revokeObjectURL() 办法让你能够创立简略的 URL 字符串,这些字符串能够用来援用任何能够应用 DOM 文件对象援用的数据,包含用户计算机上的本地文件。

对象 URL 的简略用法是:

img.src = URL.createObjectURL(file);

应用此 CodePen 能够进一步浏览对象 URL。提醒:将此办法与后面 #5 中提到的办法进行比拟。

<div>
  <h1>Use Object URL</h1>
  <input type="file" id="file-uploader" accept=".jpg, .jpeg, .png" >
  
  <div id="image-grid"></div>
</div>
const fileUploader = document.getElementById('file-uploader');
const reader = new FileReader();
const imageGrid = document.getElementById('image-grid');

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files;
  const file = files[0];
  
  const img = document.createElement('img');
  imageGrid.appendChild(img);
  img.src = URL.createObjectURL(file);
  img.alt = file.name;
});

完结

很多时候,原生 HTML 性能足以让咱们解决手中的用例。我发现,文件上传默认状况下提供了许多不错的抉择。


原文:https://dev.to/atapas

微信搜寻【前端全栈开发者】关注这个脱发、摆摊、卖货、继续学习的程序员,第一工夫浏览最新文章,会优先两天发表新文章。关注即可大礼包,准能为你节俭不少钱!

正文完
 0