使用较大文件阻止文件上传

时间:2017-03-06 16:01:13

标签: javascript reactjs redux react-redux redux-saga

简介

我想要实现的是一个简单的文件上传,带有redux-saga的进度指示并做出反应)。我在获取此指示时遇到问题,因为文件上传似乎是阻塞 - 它不应该是。

预期行为

在文件上传开始之前,会触发重新渲染并显示微调器并且窗口不会被阻止。

当前行为

我目前所拥有的是一个带有表格的组件,每个表格显示一个文件。当用户上传文件时,使用微调器添加乐观行作为内容。上传文件后,乐观行将被替换为带有文件名称等的实际行。当我上传大约50MB的文件时,窗口会被阻止,并且在文件上传前不久(大约0.5s之前)出现微调器,然后文件已经上传,微调器再次消失。

旁注

  • 如果您使用new Promise(res => setTimeout(res, 5000))替换文件上传,则一切正常=>似乎xhr / fetch存在问题。
  • 我使用XHR,promises和onProgress回调实现了相同的功能,以确保不会获取问题。 该实现看起来非常接近:https://gist.github.com/robinfehr/2f4018259bf026a468cc31100fed5c9f 此外,通过此实现,我遇到了同样的问题 - 阻塞直到上传即将结束。
  • 如果我将log语句放入组件的render函数中以查看它是否在上传文件之前重新呈现,我看到(一旦块停止并且文件被上传),渲染中的日志语句在文件上传完成之前,函数实际上是通过时间戳正确触发的。
  • 在这个实现中,我使用相同的reducer:乐观事件以及恢复乐观事件的真实事件,它们通过相同的reducer(在此处命名为fileReducer)。
  • 使用第二个reducer和concatination而不是乐观的revert逻辑有助于更早地显示微调器,但对阻塞没有帮助。因此,似乎中间件也被阻塞调用阻止。

saga :( postData使用fetch)

function* createDocument(partnerId, { payload, meta }) {
  const siteId = getSiteIdFromRoute();
  const {
    mediaGroupId,
    customArticleId,
    logicalComponentId,
    type,
    name,
    documentSrc,
    meta: metaFromFrontEnd
  } = payload;

  const commonEventId = uuid();
  const hans = {
    optimistic: true
  };
  const payloadBasic = {
    id: commonEventId,
    version: 0,
    aggregate: {
      id: uuid(),
      name: 'document'
    },
    context: {
      name: 'contentManagement'
    },
    payload: {
      name,
      type,
      links: {
        partnerId,
        siteId,
        logicalComponentId,
        customArticleId,
        mediaGroupId
      }
    }
  };

  // creates the optimistic (fake) row with a spinner in the file list component - action marked as optimistic which will be reverted.
  yield put(actions.denormalizeEvent({
    ...payloadBasic,
    name: 'documentCreated',
    optimistic: true,
    payload: {
      ...payloadBasic.payload,
      uploading: true
    }
  }));
  yield fork(executeDocumentUpload, type, siteId, partnerId, documentSrc, payloadBasic);
}

function* executeDocumentUpload(type, siteId, partnerId, documentSrc, payloadBasic) {
  const req = yield call(uploadDocument, type, siteId, partnerId, documentSrc);
  const body = yield req.json();
  const { meta: metaFromFileUpload, id } = body.response;
  // removes the optimistic (fake) row from the file list component and and adds the real row with more file information (optimistic event gets reverted in middleware)
  yield put(actions.sendCommandSuccess({
    ...payloadBasic,
    name: 'createDocument',
    payload: {
      ...payloadBasic.payload,
      meta: metaFromFileUpload
    }
  }));
}

function uploadDocument(type, siteId, partnerId, documentSrc) {
  let url;
  if (type === 'site' || type === 'mediaGroup' || type ===     'logicalComponent') {
    url = `/file/site/${siteId}/document`;
  } else if (type === 'customArticle') {
    url = `/file/partner/${partnerId}/document`;
  }
  return postData(url, documentSrc);
}

1 个答案:

答案 0 :(得分:0)

问题在于我确实将文件作为base64编码字符串发送,并使用错误的内容类型设置了请求。

'Content-Type': 'text/plain;charset=UTF-8'

将文件放入FormData对象,并将没有提及内容类型的请求发送到非阻塞请求。