axios 如何上传多个音频文件的React,但只发送3 POST请求

zdwk9cvp  于 2023-01-17  发布在  iOS
关注(0)|答案(1)|浏览(155)

我想选择100个音频文件在同一时间,但要打只有3个API调用在同一时间。一旦这3个文件上传(通过或失败),然后只有其他3 api请求将被发送。
基本上,我提供了一个文件类型的输入字段:

<input type="file" multiple name="file" className="myform"
                    onChange={handleFileChange}
                    accept="audio/wav"
                    />

我把它作为数组存储到一个状态中。下面我提供了一个上传按钮。当用户点击上传时,我想用axios发送3个POST请求。一旦所有3个都完成了,要么失败要么通过,那么只有接下来的3个应该去。

zzlelutf

zzlelutf1#

您可以通过以3个为一组迭代FileList集合并使用Promise.allSettled()并行发送请求来实现这一点。
因为我不推荐Axios,所以这里有一个使用Fetch API的版本

const BATCH_SIZE = 3;

const [fileList, setFileList] = useState([]);
const [uploading, setUploading] = useState(false);

const handleFileChange = (e) => {
  setFileList(Array.from(e.target.files)); // just a guess
};

const handleUploadClick = async (e) => {
  e.preventDefault();
  setUploading(true);
  const files = [...fileList]; // avoid mutation during long uploading process

  for (let i = 0; i < files.length; i += BATCH_SIZE) {
    const result = await Promise.allSettled(
      files.slice(i, i + BATCH_SIZE).map(async (file) => {
        const body = new FormData();
        body.append("file", file);
        const res = await fetch(UPLOAD_URL, { method: "POST", body });
        return res.ok ? res : Promise.reject(res);
      })
    );
    const passed = result.filter(({ status }) => status === "fulfilled");
    console.log(
      `Batch ${i + 1}: ${
        passed.length
      } of ${BATCH_SIZE} requests uploaded successfully`
    );
  }

  setUploading(false);
};

Promise.allSettled()将允许您在上传每组3个文件后继续,无论它们是通过还是失败。
此方法发出3个单独的请求,每个请求包含1个文件。
使用Axios时,它将如下所示(只是替换了for循环)

for (let i = 0; i < files.length; i += BATCH_SIZE) {
  const result = await Promise.allSettled(
    files
      .slice(i, i + BATCH_SIZE)
      .map((file) => axios.postForm(UPLOAD_URL, { file }))
  );
  const passed = result.filter(({ status }) => status === "fulfilled");
  console.log(
    `Batch ${i + 1}: ${
      passed.length
    } of ${BATCH_SIZE} requests uploaded successfully`
  );
}

Axios的postForm()方法从v1.0.0开始提供。请参见https://github.com/axios/axios#files-posting
如果您想在一个请求中发送3个文件,Fetch将如下所示

for (let i = 0; i < files.length; i += BATCH_SIZE) {
  const body = new FormData();
  files.slice(i, i + BATCH_SIZE).forEach((file) => {
    body.append("file", file); // use "file[]" for the first arg if required
  });
  try {
    const res = await fetch(UPLOAD_URL, { method: "POST", body });
    if (!res.ok) {
      throw new Error(`${res.status} ${res.statusText}`);
    }
    console.log(`Batch ${i + 1} passed`);
  } catch (err) {
    console.warn(`Batch ${i + 1} failed`, err);
  }
}

这是Axios的

for (let i = 0; i < files.length; i += BATCH_SIZE) {
  try {
    await axios.postForm(
      {
        file: files.slice(i, i + BATCH_SIZE),
      },
      {
        formSerializer: {
          indexes: null, // set to false if you need "[]" added
        },
      }
    );
    console.log(`Batch ${i + 1} passed`);
  } catch (err) {
    console.warn(`Batch ${i + 1} failed`, err.response?.data);
  }
}

相关问题