【问题标题】:Load image from URL and upload to media library in Strapi从 URL 加载图像并上传到 Strapi 中的媒体库
【发布时间】:2022-01-11 23:43:35
【问题描述】:

我正在为我的 Strapi 应用程序构建一个 CSV 导入器,它的任务之一是从单元格中读取图像 URL,然后从 URL 下载并将其保存到媒体库。

代码如下所示:

const request = require('request').defaults({ encoding: null });

request.get(src, function (err, res, body) {
    const fileName = src.split('/').pop();

    strapi.plugins.upload.services.upload.upload({
        files: {
            path: body,
            name: fileName,
            type: res.headers['content-type'],
            size: Number(res.headers['content-length']),
        },
        data: {
            ref: 'products',
            refId: data.itemID,
            field: 'images'
        }
    });
});

下载成功,我在request.get 回调的body 变量中获得了一个缓冲区。但是将此传递给strapi.plugins.upload.services.upload.upload 会给我以下错误:

UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_VALUE]: The argument 'path' must be a string or Uint8Array without null bytes. Received <Buffer ff d8 ff e1 10 c1 45 78 69 66 00 00 49 49 2a 00 08 00 00 00 0f 00 00 01 03 00 01 00 00 00 6c 05 00 00 01 01 03 00 01 00 ...

我已经尝试将path: body, 替换为path: new Uint8Array(body),,但没有成功。

知道我在这里做错了什么吗?

感谢您的帮助!

【问题讨论】:

  • 很明显,该函数需要一个文件路径名,而不是缓冲区。

标签: javascript node.js server strapi


【解决方案1】:

在我的一个项目中,我有同样的要求,我必须从 URL 获取文件,然后将其上传到媒体库。我首先从URL 获取字节流,然后将其保存到tmp 文件夹中的文件中,从而解决了这个问题。文件完全下载后,我只需使用strapi 的内置upload 方法将文件上传到媒体库。

需要安装的库

$ npm install mime-types
$ npm install axios
$ npm install lodash

实施
// my-project/helpers/uploader.js

const _ = require('lodash');
const axios = require('axios').default;
const fs = require('fs');
const stream = require('stream');
const path = require('path');
const promisify = require('util').promisify;
const mime = require('mime-types');

module.exports = {
  getFileDetails(filePath) {
    return new Promise((resolve, reject) => {
      fs.stat(filePath, (err, stats) => {
        if (err) reject(err.message);
        resolve(stats);
      });
    });
  },

  deleteFile(filePath) {
    return new Promise((resolve, reject) => {
      fs.unlink(filePath, (err) => {
        if (err) reject(err.message);
        resolve('deleted');
      });
    });
  },

  async uploadToLibrary(imageByteStreamURL) {
    const filePath = './tmp/myImage.jpeg';
    const { data } = await axios.get(imageByteStreamURL, {
      responseType: 'stream',
    });

    const file = fs.createWriteStream(filePath);
    const finished = promisify(stream.finished);
    data.pipe(file);
    await finished(file);
    const image = await this.upload(filePath, 'uploads');
    return image;
  },

  async upload(filePath, saveAs) {
    const stats = await this.getFileDetails(filePath);
    const fileName = path.parse(filePath).base;

    const res = await strapi.plugins.upload.services.upload.upload({
      data: { path: saveAs },
      files: {
        path: filePath,
        name: fileName,
        type: mime.lookup(filePath),
        size: stats.size,
      },
    });

    await this.deleteFile(filePath);
    return _.first(res);
  },
};

然后,在您是实际的服务/控制器时,您可以像这样简单地从您的助手中调用该方法:

const uploader = require('../../../helpers/uploader');
const img = await uploader.uploadToLibrary('http://www.example.com/demo-image.jpg');
console.log(img);
参考资料:

【讨论】:

  • 谢谢萨尔维诺!你的答案是纯金!我只需要做一些调整就可以了!
  • 很高兴为您提供帮助。编码愉快!
  • 谢谢萨尔维诺。在strapi中应该有这样的内置服务
  • 是的,完全同意这一点。
  • 非常感谢萨尔维诺!帮了我很多!!!
猜你喜欢
  • 1970-01-01
  • 2022-06-20
  • 2023-01-15
  • 2022-12-30
  • 2016-01-05
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多