'Путь должен быть строкой без нулевых байтов' при передаче потока для запроса

У меня есть буфер, созданный из изображения в формате base64. Я пытаюсь отправить с помощью POST в службу с помощью fs.createReadStream (..). Pipe (request (..)), но получаю следующую ошибку:

 Error: Path must be a string without null bytes
    at nullCheck (fs.js:135:14)
    at Object.fs.open (fs.js:626:8)
    at ReadStream.open (fs.js:1916:6)
    at new ReadStream (fs.js:1903:10)
    at Object.fs.createReadStream (fs.js:1850:10)
    at Promise (/Users/Sebbe/Documents/Code/leo-faq-service/lib/server/services/zendesk-service.js:120:10)
[...]

fs.createReadStream () принимает либо строку, либо буфер. Если это строка, то предполагается, что это путь к файлу. Мне кажется, что fs.createReadStream () пытается разрешить аргумент как строку, содержащую путь, даже если это буфер. Возможно, это ошибка в Nodes Buffer API?

Подробнее:

У меня есть служба Node, созданная с помощью Restify. У этой службы есть конечная точка, которая принимает тему, сообщение, имя и файл изображения в кодировке base64 (jpg, png и т. Д.).

Теперь мы хотим отправить содержимое файла в стороннюю службу с помощью JavaScript в Node.

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

По этой причине я создаю буфер из своего изображения в кодировке base64 и отправляю его в качестве аргумента в fs.createReadStream, который затем передаю по конвейеру объекту запроса.

В соответствии с этим я должен иметь возможность создать буфер из строки base64: https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_string_encoding

В соответствии с этим я должен иметь возможность создать читаемый поток из буфера: https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options

И в соответствии с этим я должен иметь возможность использовать модуль запроса для передачи буфера в POST-запрос: https://www.npmjs.com/package/request

Цитата из документации модуля запроса:

Вы также можете выполнить потоковую передачу файла в запрос PUT или POST. Этот метод также будет проверять расширение файла на соответствие сопоставлению расширений файлов с типами содержимого (в данном случае application / json) и использовать правильный тип содержимого в запросе PUT (если заголовки его еще не предоставляют).

fs.createReadStream ('file.json'). pipe (request.put (URL))

_postFile(base64FileContent) {
    const fileBuffer = Buffer.from(base64FileContent, 'base64');
    const fileUploadOptions = this._getRequestPostFileOptions('uploads', fileBuffer.length);

    return new Promise((resolve, reject) => {
      fs.createReadStream(fileBuffer)
        .pipe(request.post(fileUploadOptions)
          .on('response', (response) => {
            resolve(response);
          })
          .on('error', (error) => {
            reject(error);
          })
        );
    });
  }

  _getRequestPostFileOptions(resourceName, dataLength) {

    return {
      uri     : url.parse(`${this.coreBaseUrl}/${resourceName}`),
      timeout : RequestTimeout,
      method  : 'POST',
      headers : {
        'Authorization'  : `Basic ${this.auth}`,
        'Content-Type'   : 'application/binary',
        'Content-Length' : dataLength
      }
    };
  }


person Spetastium    schedule 03.10.2016    source источник
comment
Что это возвращает url.parse('${this.coreBaseUrl}/${resourceName}')?   -  person David R    schedule 03.10.2016
comment
пример: this.coreBaseUrl = 'url.to/api' resourceName = 'article' или 'user' или 'comments'. Затем я использую url.parse (..), чтобы объединить их в действительный URL.   -  person Spetastium    schedule 03.10.2016
comment
Можете ли вы подтвердить, будет ли он передан в виде строки после того, как вы выполните url.parse(..)?   -  person David R    schedule 03.10.2016
comment
Да, синтаксический анализ URL-адреса с помощью url.parse и буквальных шаблонов выполняется и в других местах, и он отлично работает.   -  person Spetastium    schedule 03.10.2016
comment
Есть обновления по этому поводу? Такая же проблема.   -  person dwhieb    schedule 04.12.2016


Ответы (1)


fs.createReadStream() всегда принимает путь к файлу в качестве первого аргумента. Похоже, вы действительно передаете содержимое некоторого двоичного файла в качестве аргумента пути к файлу для fs.createReadStream(). Если мое предположение верно, тогда вам просто нужно передать Buffer в качестве тела request() следующим образом:

return new Promise((resolve, reject) => {
  fileUploadOptions.body = fileBuffer;
  request.post(fileUploadOptions)
         .on('response', (response) => {
           resolve(response);
          })
         .on('error', (error) => {
           reject(error);
         });
});
person mscdex    schedule 03.10.2016
comment
Спасибо, я протестирую это и вернусь с результатами. - person Spetastium; 03.10.2016
comment
Согласно документации, буфер может быть первым аргументом. - person Grant; 11.10.2017
comment
@ Да, да, вы можете использовать объекты Buffer для путей к файлам в fs в последних версиях узла, но это не имеет отношения к этой ситуации, потому что не должно быть нулевых байтов, поэтому ввод пути к файлу особенно подозрительный. - person mscdex; 11.10.2017