Ошибка Axios: … .data.pipe не является функцией

#javascript #node.js #axios

#javascript #node.js #axios

Вопрос:

Итак, я в основном пытаюсь использовать axios для загрузки изображения с URL-адреса, но я получаю эту ошибку:

TypeError: streamResponse.data.pipe is not a function

Моя функция для загрузки этого изображения приведена ниже (обратите внимание, что это внутри класса):

 /**
 * Download poster
 */
async downloadPoster() {

    // Writer stream where we want to download the poster image
    const writer = fs.createWriteStream(this.poster.file);

    // This grabs the second part of the image url that we want
    const resultsResponse = await axios({
        url: this.poster.url,
        method: 'GET',
        responseType: 'json',
        adapter: httpAdapter
    });

    // Zero results
    if (resultsResponse.data.total_results <= 0) {
        logger.log(language[Config.language].posterNotFound   this.movie.title, 'error');
        return false;
    }

    // Create the poster download URL
    var posterDownloadUrl = new URL(Config.api.posterUrl   resultsResponse.data.results[0].poster_path);

    const streamResponse = await axios({
        url: posterDownloadUrl,
        method: 'GET',
        responseType: 'stream',
        adapter: xhrAdapter
    });

    // Write data
    streamResponse.data.pipe(writer);

    return new Promise((resolve, reject) => {
        writer.on('finish', resolve);
        writer.on('error', reject);
    });

}
 

Я предполагаю, что адаптером для ответа потока является xhr. В любом случае, я пробовал оба адаптера, и оба выдают одну и ту же ошибку. Хотя оба запроса происходят (я вижу их в devtools).

И чтобы не было путаницы, у меня есть адаптеры, импортированные в верхней части файла:

const httpAdapter = require('axios/lib/adapters/http');
const xhrAdapter = require('axios/lib/adapters/xhr');

Что я могу здесь делать не так?

Ответ №1:

вот более простая версия вашего кода.

Код:

 const downloadImage = async (url) => {
    // Writer stream where we want to download the image
    const writer = fs.createWriteStream("./image.png");

    const streamResponse = await axios({
        url,
        method: 'GET',

        // that the point!!!
        // change responseType to stream
        // pipe only work with 'stream'
        responseType: 'stream'
    });

    // Write data
    streamResponse.data.pipe(writer);

    writer.on('finish', () => console.log("Finished"));
    writer.on('error', () => console.error("Error while dowloading image"));
}
const imageLink = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1200px-Image_created_with_a_mobile_phone.png";
downloadImage(imageLink);
 

Комментарии:

1. Я не могу это использовать, так как ссылка на изображение генерируется путем выполнения запроса axios первым. Таким образом, должно быть 2 запроса axios. 1 для захвата ссылки на изображение и один для захвата фактического изображения.

2. Ваша проблема заключалась в потоковой передаче второго запроса Axios в файл, верно? Моя более простая версия кода делает это. Я предположил, что ваш первый запрос Axios работает, если это так, вы можете создать свой второй запрос так же, как я сделал ошибку, изменив только параметр URL.

3. Ооо .. кажется, я понимаю. Итак, в основном код, который вы предоставили, а затем вторая функция для получения правильного URL-адреса изображения? const const imageUrl = async () => { ... }

4. Вы можете использовать именно тот код, который у вас уже есть. Но при втором запросе axios вам необходимо удалить параметр «adapter». Это должно сработать.

5. Попытался изменить второй запрос, удалив параметр адаптера, но получил точно такую же ошибку. Я попытаюсь использовать две функции, ту, которую вы предоставили, и одну для получения правильного URL-адреса изображения.

Ответ №2:

Заставил его работать, отправив запрос на загрузку в основной поток. Не знаю почему, но, похоже, вы не можете получить доступ к данным axios из потока в renderer.js файле. Теперь это работает, хотя после просмотра здесь:

https://www.electronjs.org/docs/api/ipc-main

Комментарии:

1. Для тех, кто смотрит на это: решение состоит в том, чтобы отправить сообщение из процесса визуализации в основной процесс. Основным процессом будет запуск для запуска axios.

Ответ №3:

если вы используете electron, это альтернатива. в quasar это работает отлично. Не забудьте вставить в main.js of electron nodeIntegration = true

 const fs = require('fs-extra');
import path from 'path';

let url = 'yourl.com';
axios({
        url,
        method: 'GET',
        responseType: 'blob'
}).then((res) => {
    let fileName='myfile.zip'

    const dir = path.dirname(__dirname);
    const Path = path.resolve(`${dir}/dir`, 'subdir', fileName);

    const output = fs.createWriteStream(Path);
    const ws = new WritableStream(output)        

    let blob = new Blob([res.data], {type: 'application/zip'})
    
    const stream =  blob.stream();
    
    //optional
    //stream.pipeTo(ws).then(console.log('Done!!!'));

    stream.pipeTo(ws);
  })
 

Ответ №4:

Вы должны быть добавлены responseType как AxiosRequestConfig, а не заголовок

  const response = await axios(`${url}/api/v1/rest/export`, {
      method: 'POST',
      responseType: 'stream',
      headers: {
        'Content-Type': 'application/json',
        Authorization: authToken.includes('Bearer') ? authToken : `Bearer ${authToken}`,
      },
      data: query,
    });
    response.data.pipe(fs.createWriteStream('./export.csv'));