export function createUploadHandler()

in packages/app/main/src/server/routes/directLine/handlers/upload.ts [48:138]


export function createUploadHandler(emulatorServer: EmulatorRestServer) {
  const {
    logger: { logMessage },
    state,
  } = emulatorServer;

  return (req: Request, res: Response, next: Next): any => {
    if (req.params.conversationId.includes('transcript')) {
      res.end();
      next();
      return;
    }

    const conversation: Conversation = (req as any).conversation;
    const botEndpoint: BotEndpoint = (req as any).botEndpoint;

    if (!conversation) {
      res.send(HttpStatus.NOT_FOUND, 'conversation not found');
      res.end();
      logMessage(req.params.conversationId, textItem(LogLevel.Error, 'Cannot upload file. Conversation not found.'));
      next();
      return;
    }

    if (req.getContentType() !== 'multipart/form-data' || (req.getContentLength() === 0 && !req.isChunked())) {
      next();
      return;
    }

    const form = new Formidable.IncomingForm({ keepExtensions: true, multiples: true });

    // TODO: Override form.onPart handler so it doesn't write temp files to disk.
    form.parse(req, async (err: any, fields: any, files: any) => {
      try {
        const activity = JSON.parse(fs.readFileSync(files.activity.path, 'utf8'));
        let uploads = files.file;

        if (!Array.isArray(uploads)) {
          uploads = [uploads];
        }
        if (uploads && uploads.length) {
          const serviceUrl = await emulatorServer.getServiceUrl(botEndpoint.botUrl);
          activity.attachments = [];
          uploads.forEach(upload1 => {
            const name = (upload1 as any).name || 'file.dat';
            const type = upload1.type;
            const path = upload1.path;
            const base64EncodedContent = fs.readFileSync(path, { encoding: 'base64' });
            const base64Buf = Buffer.from(base64EncodedContent, 'base64');
            const attachmentData: AttachmentData = {
              type,
              name,
              originalBase64: new Uint8Array(base64Buf),
              thumbnailBase64: new Uint8Array(base64Buf),
            };
            const attachmentId = state.attachments.uploadAttachment(attachmentData);
            const attachment: Attachment = {
              name,
              contentType: type,
              contentUrl: `${serviceUrl}/v3/attachments/${attachmentId}/views/original`,
            };

            activity.attachments.push(attachment);
          });

          try {
            const { updatedActivity, statusCode, response } = await conversation.postActivityToBot(activity, true);

            if (~~statusCode === 0 && ~~statusCode > 300) {
              res.send(statusCode || HttpStatus.INTERNAL_SERVER_ERROR, await response.text());
              res.end();
            } else {
              res.send(statusCode, { id: updatedActivity.id });
              res.end();
              WebSocketServer.sendToSubscribers(conversation.conversationId, updatedActivity);
            }
          } catch (err) {
            sendErrorResponse(req, res, next, err);
          }
        } else {
          res.send(HttpStatus.BAD_REQUEST, 'no file uploaded');
          res.end();
        }
      } catch (e) {
        sendErrorResponse(req, res, next, e);
      }

      next();
    });
  };
}