文件的上传与下载

150 阅读3分钟

文件上传

普通文件

<img src="" alt="" id="imgUrl">
  <label for="oFile">
    <input
      type="file"
      id="oFile"
      name="myFiles"
      multiple
      accept=".jpg, .jpeg .png, .gif, .bmp"
      onchange="upFile(event)"
    />
  </label>
  <script>
  普通文件上传
    // function upFile(event) {
    //   const file =
    //     event.target.files[0] ||
    //     event.dataTransfer.files[0] ||
    //     this.file.files[0];
    //   console.dir(file); // 文件对象
    //   console.log(file.name); // 文件名称
    //   console.log(file.type); // 文件类型
    //   console.log(file.size); // 文件大小

    //   // 对文件类型做简单限制:如:只允许上传 jpg  png gif 这3种格式
    //   if (!file.type && /\.(?:jpg|png|gif)$/.test(file.name)) {
    //     alert("对不起:上传的图片格式只能是:jpg, png, gif");
    //     return false;
    //   }

    //   // 使用FormData方式上传,并设置相应的参数
    //   const fData = new FormData();
    //   fData.set("myFiles", file); // 设置上传属性
    //   fData.set("myxxx", "abcdef"); // 设置自定义上传参数
    //   fData.append("name", file.name); // 添加上传信息
    //   fData.append("type", file.type); // 添加上传信息
    //   fData.append("size", file.size); // 添加上传信息
    //   fData.append("id", 666); // 添加上传信息
    //   // 限制文件大小在500KB以内
    //   if (file.size / 1024 > 500) {
    //     alert("对不起:上传的文件不能大于500KB");
    //     return false;
    //   }

    //   // 限制文件大小在2MB以内
    //   if (file.size / 1024 / 1024 > 2) {
    //     alert("对不起:上传的文件不能大于2MB");
    //     return false;
    //   }

    //   // 还可以用乘法来计算上传文件大小
    //   // 1KB = 1 * 1024;
    //   // 1MB = 1 * 1024 * 1024;
    //   // 1GB = 1 * 1024 * 1024 * 1024;

    //   // 限制文件大小在3MB以内
    //   if (file.size > 3 * 1024 * 1024) {
    //     alert("对不起:上传的文件不能大于3MB");
    //     return false;
    //   }
    // }
图片文件上传预览
    function upFile(event) {
      const file =
        event.target.files[0] ||
        event.dataTransfer.files[0] ||
        this.file.files[0];
      // 图片预览1
      const createObjectURL =
        window.createObjectURL ||
        window.URL.createObjectURL ||
        window.webkitURL.createObjectUR;
      console.log(createObjectURL(file));

      // 图片预览2
      const fr = new FileReader();
      fr.readAsDataURL(file); // Base64 8Bit字节码
      // fr.readAsBinaryString(file);  // Binary 原始二进制
      // fr.readAsArrayBuffer(file);   // ArrayBuffer 文件流
      fr.onload = function (res) {
        console.log(this.result);
        console.log(res.target.result);
        console.log(res.srcElement.result);
        document.querySelector("#imgUrl").src=res.target.result;
      };

      // 注意:当第二次再次选择之前的那个文件后,onchange事件不触发,所以要清空一下value
      if (event.target.outerHTML) {
          event.target.outerHTML = event.target.outerHTML;
        } else {
          event.target.value = "";
        }
    }

   

    
  </script>

大文件上传

在上传大文件时,通常采用分块上传的方式。将大文件分成若干个块,每块一个 HTTP 请求上传。

实现大文件上传的步骤如下:

用户选择文件。 将文件分成若干块。 对于每一块,向服务器发送 HTTP 请求上传。 服务器接收到文件块后,将其存储在服务器上。 在所有块上传完成后,服务器将所有块合并成一个完整的文件。 JavaScript 可以使用 File API(File 和 Blob 对象)来实现文件的读取和上传。

下面是一个使用 JavaScript 实现大文件上传的简单实例,使用分块上传的方法。

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

// 上传文件块
function uploadChunk(file, start, end, chunk) {
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/upload', true);
    xhr.setRequestHeader('Content-Type', 'application/octet-stream');
    xhr.setRequestHeader('Content-Range', 'bytes ' + start + '-' + end + '/' + file.size);
    xhr.send(chunk);
}
 
// 上传文件
function uploadFile(file) {
    var chunkSize = 1 * 1024 * 1024; // 分块大小为1MB
    var chunks = Math.ceil(file.size / chunkSize); // 计算分块数
    var currentChunk = 0; // 当前分块
    var start, end;
    while (currentChunk < chunks) {
        start = currentChunk * chunkSize;
        end = start + chunkSize >= file.size ? file.size : start + chunkSize;
        var chunk = file.slice(start, end);
        uploadChunk(file, start, end, chunk);
        currentChunk++;
    }
}
 
// 监听文件选择事件
document.getElementById('file-input').addEventListener('change', function(e) {
    var file = e.target.files[0];
    if (file) {
        uploadFile(file);
    }

在这个实例中,我们使用了 XMLHttpRequest 对象上传文件,并设置了 Content-Type 和 Content-Range 消息头。Content-Type 消息头表示上传的数据类型是二进制数据,Content-Range 消息头表示上传的文件块的范围。

在这个示例中,我们将文件分成若干块,每块大小为 1MB。我们使用 File API 中的 slice 方法截取文件块,并使用 XMLHttpRequest 将文件块上传到服务器。

注意,这只是一个简单的实例,代码仅供参考,在实际应用中还需要考在考虑以下几点:

如果服务器端支持断点续传,可以在服务器端记录已经上传的文件块,避免重复上传。 需要考虑如何处理上传失败的文件块,是否需要重试。 在上传过程中需要提供进度条,让用户了解上传进度。 在上传完成后需要有反馈,告知用户上传是否成功。 服务器端如何处理上传的文件块,将其合并成一个完整的文件。 服务器端存储空间的问题。可以使用分布式文件系统(如 HDFS)或云存储(如 Amazon S3)来存储上传的文件。 文件块上传顺序、文件块校验、断点续传等问题。 通过分块上传的方式,我们可以将大文件分成若干块上传,避免一次性上传大文件造成的超时或者内存不足的问题,同时也方便实现断点续传和上传进度的显示。

文件下载

在 JavaScript 中实现文件下载,常见的方法如下:

1、使用 window.location 实现:通过更改当前页面的 URL 为文件下载地址,从而实现下载。

window.location = 'file-download-url';

2、使用 a 标签实现:通过创建一个 a 标签并设置其 href 和 download 属性,从而实现下载。

<div class="downLoad">
    <button class="down" onclick="downloadByUrl('https://img2.baidu.com/it/u=18987873,4170161074&fm=253&fmt=auto&app=138&f=JPG?w=650&h=423','图片')">下载</button>
</div>
<script>
  const downloadByUrl = (url, filename) => {
      if (!url) throw new Error("当前没有下载链接");

      const a = document.createElement("a");
      a.style.display = "none";
      a.href = url;
      a.download = filename;
      // 使用target="_blank"时,添加rel="noopener noreferrer" 堵住钓鱼安全漏洞 防止新页面window指向之前的页面
      a.rel = "noopener noreferrer";
      document.body.append(a);
      // let blob = new Blob(["https://img2.baidu.com/it/u=18987873,4170161074&fm=253&fmt=auto&app=138&f=JPG?w=650&h=423"], { type: "image/png" });

      // a.href = URL.createObjectURL(blob);
      a.click();

      setTimeout(() => {
        a.remove();
      }, 1000);
    };
    </script>

3、使用 fetch API 实现:通过使用 fetch API 获取文件内容,并将其写入 Blob 对象,最后利用 URL.createObjectURL 将其下载。

fetch('file-download-url')
  .then(response => response.blob())
  .then(blob => {
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'filename';
    link.click();
    URL.revokeObjectURL(url);
    document.body.removeChild(link);
  });