Инициировать загрузку файла HTTP, прочитав файл из другого HTTP-запроса, состоящего из нескольких частей.

Конечная точка загрузки получает данные от клиента в составном файле. Этот файл снова отправляется в качестве параметра для нового HTTP-вызова, сделанного из той же службы.

//Клиент загружает код файла

form(enctype="multipart/form-data", action="/data/upload", method="post")
  input(type="file", name="data")

Я хочу прочитать этот файл и загрузить его в другую конечную точку Java, которая принимает файл.

Я попытался получить поток файлов через busBoy и преобразовал его в строку, попытался преобразовать строку обратно в поток и передал ее новому запросу. Но это не удается из службы Java.

import axios from 'axios';

const FormData = require('form-data');
const { Readable } = require('stream');

const fileBufferChunks = [];

busBoyStream.on('file', (fieldname, file, filename, encoding, mimetype) => {
  file.on('data', (data) => {
    fileBufferChunks.push(data);
  });
  file.on('end', () => {
    console.log(` ${filename} file parsed from req`);
    const fileString = Buffer.concat(fileBufferChunks).toString('base64');
    const data = new FormData();
    const readableStream = Readable.from([fileString]);
    data.append('file_param', readableStream);
    const headers = data.getHeaders();
    const axiosConfig = {
      method: 'post',
      url: URL,
      headers: {
        ...headers,
      },
      data,
    };

    axios(axiosConfig)
      .then((response) => {
        console.log('job trigger success');
      });
  });
});
      

Но если я сохраняю файл локально и передаю тот же файловый поток через fs.createReadStream, он работает.


import axios from 'axios';

const FormData = require('form-data');
const fs = require('fs');

const fileBufferChunks = [];

busBoyStream.on('file', (fieldname: any, file: any, filename: any, encoding: any, mimetype: any) => {
  file.on('end', () => {
    const data = new FormData();
    const saveTo = '/dummypath/name.csv';
    file.pipe(fs.createWriteStream(saveTo));
    data.append('file_param', fs.createReadStream('/dummypath/name.csv'));
    const headers = data.getHeaders();
    const axiosConfig = {
      method: 'post',
      url: URL,
      headers: {
        ...headers,
      },
      data,
    };

    axios(axiosConfig)
      .then((response) => {
        console.log('job trigger success');
      });
  });
});

Я хочу понять, в чем разница между потоком, который создается путем преобразования файла в строку и создания потока из этой строки файла, и потока, созданного с использованием fs.createReadStream(pathToFile)

Может ли кто-нибудь объяснить, почему существует разница в поведении и каков рекомендуемый способ отправки загрузки файла из одного HTTP-запроса в другой запрос...?


person AnandShiva    schedule 20.11.2020    source источник


Ответы (1)


Проблема заключалась в обработке свойств файла с библиотекой form-data, которая преобразует потоки в formdata. конкретная полезная нагрузка.

Библиотека form-data автоматически заполняет информацию о contentType файла, если поток fs создан файловый поток. Так что он отлично работал с файловыми потоками fs. В моем случае поток является читаемым файловым потоком из библиотеки потоков, поэтому мне нужно вручную предоставить информацию о типе содержимого, как показано в примере ниже.

data.append(uploadFile.fieldname, uploadFile.file, {
   filename: 'filename.csv', // ... or:
   //   filepath: 
   contentType: 'text/csv',
   // knownLength: 5,
 });

Библиотека form-data для обработки файлов требует, чтобы многие свойства файлов, подобные этому, были предоставлены для пользовательских объектов потока. Полный список можно найти в их документации.

person AnandShiva    schedule 26.11.2020