Estoy creando un importador de CSV para mi aplicación Strapi y una de sus tareas es leer una URL de imagen desde una celda y descargarla desde la URL y guardarla en la biblioteca de medios.
El código se ve así:
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' } }); });
La descarga funciona y obtengo un búfer en la variable del body
de la devolución de llamada request.get
. Pero pasar esto a strapi.plugins.upload.services.upload.upload
me da el siguiente error:
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 ...
Ya intenté reemplazar path: body,
con path: new Uint8Array(body),
pero sin suerte.
¿Alguna idea de lo que hago mal aquí?
¡Gracias por tu ayuda!
Tenía exactamente el mismo requisito en uno de mis proyectos en el que tenía que obtener un archivo de una URL
y luego subirlo a la biblioteca de medios. Abordé el problema obteniendo primero el flujo de bytes de la URL
y luego guardándolo en un archivo en una carpeta tmp
. Una vez que el archivo se ha descargado por completo, simplemente utilicé el método de upload
incorporado de strapi
para cargar el archivo en la biblioteca de medios.
$ 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); }, };
Luego, en su servicio/controlador real, simplemente puede invocar el método de su ayudante de la siguiente manera:
const uploader = require('../../../helpers/uploader'); const img = await uploader.uploadToLibrary('http://www.example.com/demo-image.jpg'); console.log(img);