• 你有在上传文件下载文件踩过坑吗?


    上传

    上传文件的需求很常见,但还是很容易踩坑,特别是对于之前没用做过类似需求的小伙伴。

    • 首先文件上传请求的参数传递方式通常使用 multipart/form-data 格式。这是一种专门用于在 HTTP 请求中传递二进制文件数据的标准方法。
     fetch('/upload', {
        method: 'POST',
        headers: {
          'Content-Type': 'multipart/form-data',
        },
        body: JSON.stringify(data),
      })
        .then(response => response.json())
        .then(data => {
          console.log('Response from server:', data);
        })
        .catch(error => {
          console.error('Error:', error);
        });
    // axios
    axios.post(url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data', // 设置请求头
      },
    })
      .then(response => {
        console.log('Response from server:', response.data);
        // 处理成功响应
      })
      .catch(error => {
        console.error('Error:', error);
        // 处理错误
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 获取文件内容,表单提交时和其他字段信息一起上传
      1. 传统的html
    <input type="file" id="fileInput">
    <button onclick="readFile()">Read Filebutton>
    
    • 1
    • 2
    function readFile() {
      const fileInput = document.getElementById('fileInput');
      const file = fileInput.files[0]; // 获取选择的文件
    
      if (file) {
        const reader = new FileReader();
        reader.onload = function (event) {
          const fileContent = event.target.result;
          // 在这里处理文件内容
          console.log('File content:', fileContent);
          // 在此可以将文件内容与其他信息一起提交到后端
          // 使用 fetch 或其他 AJAX 方法将数据发送到后端
        };
        reader.readAsText(file); // 使用文本格式读取文件
      } else {
        console.log('No file selected.');
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 基于ant design
      我这里些了多个显示文件的格式。在实际的需求中可以参考使用
    import React, { useState } from "react";
    import { Input, Tag, Upload } from "antd";
    import { DeleteOutlined, FolderOpenOutlined } from "@ant-design/icons";
    import _ from "lodash";
    
    import "./style.less";
    const UploadCom = () => {
      const [fileList, setFileList] = useState<any>([]);
    
      const renderList = () => {
        return (
          <div className="tagWrapper">
            {_.map(fileList, (file: any) => {
              return (
                <Tag
                  key={file.uid}
                  className="tag"
                  closable
                  onClose={() => {
                    setFileList((pre: any) =>
                      _.filter(pre, (p) => p?.uid !== file.uid)
                    );
                  }}
                >
                  <span className="tagText">{file?.name}</span>
                </Tag>
              );
            })}
          </div>
        );
      };
      return (
        <div className="uploadWrapper">
          <div>
            <p>tag形式上传多个文件:</p>
            <Upload
              fileList={[]}
              multiple={true}
              showUploadList={false}
              beforeUpload={(file) => {
                setFileList((pre: any) => [...pre, file]);
                // 如果是在表单里统一提交。这里需要return false
                return false;
              }}
            >
              {/* 文件样式展示多个tag */}
              {renderList()}
            </Upload>
          </div>
    
          <div style={{ margin: "20px 0" }}>
            <p>上传单个文件输入框类型:</p>
            <Upload
              fileList={[]}
              multiple={true}
              showUploadList={false}
              beforeUpload={(file) => {
                setFileList((pre: any) => [...pre, file]);
                // 如果是在表单里统一提交。这里需要return false
                return false;
              }}
            >
              {/* 单个文件显示文件名 */}
              <Input
                placeholder="请选择文件"
                value={fileList?.[0]?.name}
                prefix={
                  <FolderOpenOutlined style={{ color: "rgba(0,0,0,0.65)" }} />
                }
              />
            </Upload>
          </div>
    
          <div>
            <p>列表形式:</p>
            {_.map(fileList, (file) => {
              return (
                <div className="file-list-item">
                  <div> {file.name}</div>
                  <DeleteOutlined
                    onClick={() => {
                      setFileList((pre: any) =>
                        _.filter(pre, (p) => p?.uid !== file.uid)
                      );
                    }}
                  />
                </div>
              );
            })}
          </div>
        </div>
      );
    };
    export default UploadCom;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    style

    .uploadWrapper{
      padding: 24px;
      .tagWrapper{
        display: flex;
        align-items: center;
        width: 300px;
        height: 32px;
        border: 1px solid #d9d9d9;
        padding: 0 12px;
    
        .tag{
          width: 80px;
          display: flex;
          align-items: center;
        
          .tagText{
            width: 50px;
            display: inline-block;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
        }
      }
      .file-list-item{
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 300px;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    下载

    • 下载文件就需要指定响应文件格式responseType为blob二进制文件流,否则很可能打不开文件,说文件内容被损坏。
    • 创建一个 Blob 对象,并将其转换为下载链接
    import axios from 'axios';
    
    const url = '/download'; // 下载文件的后端端点
    
    axios.get(url, {
      responseType: 'blob', // 指定响应类型为二进制数据(Blob)
    })
      .then(response => {
        const blob = new Blob([response.data]{ type: 'text/plain' }); // 文本文档为例
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'filename.ext'; // 设置下载的文件名
        a.style.display = 'none';
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
      })
      .catch(error => {
        console.error('Error:', error);
        // 处理下载失败
      });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    其他文件类型

    在创建 Blob 对象时,根据文件类型指定 type 参数的值。

    1. JSON 文件

      • application/json:用于表示 JSON 数据。
      • 示例:
        const jsonBlob = new Blob([jsonData], { type: 'application/json' });
        
        • 1
    2. ZIP 文件

      • application/zip:用于表示 ZIP 压缩文件。
      • 示例:
        const zipBlob = new Blob([zipData], { type: 'application/zip' });
        
        • 1
    3. Excel 文件

      • 对于旧版的 Excel 文件(.xls):application/vnd.ms-excel
      • 对于新版的 Excel 文件(.xlsx):application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
      • 示例:
        const excelBlob = new Blob([excelData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
        
        • 1
    4. Word 文件

      • 对于旧版的 Word 文件(.doc):application/msword
      • 对于新版的 Word 文件(.docx):application/vnd.openxmlformats-officedocument.wordprocessingml.document
      • 示例:
        const wordBlob = new Blob([wordData], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
        
        • 1

    本文总结的只是个人经验,如有问题,不吝指教。

  • 相关阅读:
    我的AI音乐梦:ChatGPT帮我做专辑
    校园棒球运动会运营策划案·棒球联盟
    GmNAC181促进结瘤并提高根瘤的耐盐性
    目标检测模型的评价标准-AP与mAP
    Aspose.Words使用教程之插入文档元素(三)
    Eureka的设计理念
    抽象工厂模式
    云上360行丨深耕快消品行业数字化转型,纷享销客与华为云合力同行
    Cocoa Application-基础
    ansible及其模块
  • 原文地址:https://blog.csdn.net/study_way/article/details/133378570