React の antdPro にファイル インポートを実装する - コードと落とし穴レコードを実装する

必要:

Web 側のバックグラウンド管理プロジェクトでは、ファイルのアップロードおよびインポート機能を実装し、インポート エラー メッセージとプロンプトを返し、インポートされたデータをテーブルに表示する必要があります。

環境:

反応@17 + Ant Design [email protected] + [email protected]

プロセス中に発生した問題:

  1. アップロードされたファイルにエラーがある場合、バックエンドは間違ったファイル ストリームを直接返します (応答は文字化けします)。これをフロントエンドから取得するのは困難です。----解決策: 要求時に構成を追加します。responseType: 'blob'。これにより、ファイル ストリームを読み取れるようになります。
  2. responseType が「blob」の場合、アップロードが成功しても失敗しても blob 形式が返されるため、アップロードが成功したか失敗したかを区別することが困難になります。----解決策: blob に type 属性があるので、res.type が application/json であるかどうかを判断すると、成功と失敗で type の型が異なることがわかり、type 属性を判断することができます。自分のインターフェース状況の成功か失敗かを判断するため。
  3. 正常にインポートされたデータの数と失敗したデータの数をユーザーに要求する必要がありますが、インターフェイスによって返される形式は次のとおりです: 成功した場合、応答で {successNum: 2, failedNum: 0} が返されます。 blob を読み取って json.to; に変換することで取得できますが、失敗した場合、応答はドキュメント ストリームを直接返し、バックエンドはレイヤーを外側にラップできないため、成功と失敗の数が応答ヘッダーの「Content-Disposition」フィールド。この番号を取得するときに、次の 2 つの問題が発生しました: ①. リクエストは umi のリクエストを使用しており、返されるデータは axios の完全な応答構造ではなく、直接バックエンド データであるため、このリクエストに設定を個別に追加する必要があります。 getResponse : true } 完全な応答を返し、応答ヘッダーのコンテンツを取得します; ②. ヘッダーの Content-Type フィールドは取得できますが、「Content-Disposition」は取得できません。ネットワーク応答ヘッダーをこれらのフィールドに追加します。フロントエンドがこのフィールドを取得できるようになる前に、バックエンドを設定してこのフィールドを公開する必要があります。
  4. インポートとは関係のない別の問題ですが、関数のパラメータの受け渡しの問題: 関数の最初のパラメータは渡す必要がありますが、2 番目と 3 番目のパラメータは必要ありません。ただし、最初のパラメータだけを渡したいのです。そして3番目のパラメータ。次に、2 番目のパラメーターの位置に、unknown または null を渡すことができます。

コード:

1.インポートボタン

テーブル コンポーネントが ProTable の場合、ツールバーにボタンを追加します --toolBarRender

 toolBarRender={() => [
                <Upload
                  beforeUpload={beforeUpload}
                  accept=".xls,.xlsx"
                  showUploadList={false}
                  key="push"
                >
                  <Button type="primary">导 入</Button>
                </Upload>,
              ]}

2.インポート方法

 const beforeUpload = async (file: RcFile) => {
    //文件格式及大小的校验
    const isExcel =
      file.type === 'application/vnd.ms-excel' ||
      file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    if (!isExcel) {
      message.error('文件格式不正确!');
      return;
    }
    const isLt2M = file.size / 1024 / 1024 < 2;
    if (!isLt2M) {
      message.error('上传的文件不要超过2M');
      return;
    }
    //给后端发请求----添加responseType及getResponse配置
    const res = await api.transportation.uploadUsingPOST({ file }, undefined, {
      responseType: 'blob',
      getResponse: true,
    });
    //判断是否全部导入成功还是有错误数据
    if (res.data.type !== 'application/json') {
      //获取响应头中拼接的成功条数和失败条数数据
      const headerContent = res.response.headers?.get('Content-Disposition')?.split(';');
      const successNum = headerContent?.[2].split('=')[1];
      const failNum = headerContent?.[3].split('=')[1];
    //如果成功0条,直接提示导入失败
      if (successNum == 0) {
        notification.error({
          message: '数据导入失败',
          description: `${failNum} 条数据导入失败,正在下载错误信息文件`,
          placement: 'top',
        });
      } else {
    //如果有成功的,则刷新表格,提示部分失败
        actionRef.current?.reload();
        notification.warning({
          message: '部分数据导入失败',
          description: `${successNum} 条数据导入成功;\n${failNum} 条数据导入失败,正在下载错误信息文件`,
          placement: 'top',
        });
      }

      //如果后台返回流,说明有数据导入失败,则自动下载导入失败数据的excel表
      const link = document.createElement('a');
      const blob = new Blob([res.data as Blob], { type: 'application/x-excel' });
      link.style.display = 'none';
      link.href = URL.createObjectURL(blob);
      const filename = '导入失败数据.xlsx';
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } else {
      //如果全部导入成功,则读取blob,拿到返回数据,提示用户
      const reader = new FileReader();
      reader.readAsText(res.data as Blob, 'utf-8');
      reader.onload = () => {
        const data = JSON.parse(reader.result); //这里转json格式
        notification.success({
          message: '数据导入成功',
          description: `已成功导入 ${data['成功条数']} 条数据`,
          placement: 'top',
        });
      };
      actionRef.current?.reload();
    }
  };

ご質問がございましたら、お気軽にご相談ください。

おすすめ

転載: blog.csdn.net/weixin_62192841/article/details/133065100