@strapi/data-transfer
Version:
Data transfer capabilities for Strapi
122 lines (119 loc) • 4.63 kB
JavaScript
import { join } from 'path';
import { Duplex, PassThrough, Readable } from 'stream';
import { createReadStream, stat } from 'fs-extra';
function getFileStream(filepath, strapi1, isLocal = false) {
if (isLocal) {
// Todo: handle errors
return createReadStream(filepath);
}
const readableStream = new PassThrough();
// fetch the image from remote url and stream it
strapi1.fetch(filepath).then((res)=>{
if (res.status !== 200) {
readableStream.emit('error', new Error(`Request failed with status code ${res.status}`));
return;
}
if (res.body) {
// pipe the image data
Readable.fromWeb(res.body).pipe(readableStream);
} else {
readableStream.emit('error', new Error('Empty data found for file'));
}
}).catch((error)=>{
readableStream.emit('error', error);
});
return readableStream;
}
function getFileStats(filepath, strapi1, isLocal = false) {
if (isLocal) {
return stat(filepath);
}
return new Promise((resolve, reject)=>{
strapi1.fetch(filepath).then((res)=>{
if (res.status !== 200) {
reject(new Error(`Request failed with status code ${res.status}`));
return;
}
const contentLength = res.headers.get('content-length');
const stats = {
size: contentLength ? parseInt(contentLength, 10) : 0
};
resolve(stats);
}).catch((error)=>{
reject(error);
});
});
}
async function signFile(file) {
const { provider } = strapi.plugins.upload;
const { provider: providerName } = strapi.config.get('plugin.upload');
const isPrivate = await provider.isPrivate();
if (file?.provider === providerName && isPrivate) {
const signUrl = async (file)=>{
const signedUrl = await provider.getSignedUrl(file);
file.url = signedUrl.url;
};
// Sign the original file
await signUrl(file);
// Sign each file format
if (file.formats) {
for (const format of Object.keys(file.formats)){
await signUrl(file.formats[format]);
}
}
}
}
/**
* Generate and consume assets streams in order to stream each file individually
*/ const createAssetsStream = (strapi1)=>{
const generator = async function*() {
const stream = strapi1.db.queryBuilder('plugin::upload.file')// Create a query builder instance (default type is 'select')
// Fetch all columns
.select('*')// Get a readable stream
.stream();
for await (const file of stream){
const isLocalProvider = file.provider === 'local';
if (!isLocalProvider) {
await signFile(file);
}
const filepath = isLocalProvider ? join(strapi1.dirs.static.public, file.url) : file.url;
const stats = await getFileStats(filepath, strapi1, isLocalProvider);
const stream = getFileStream(filepath, strapi1, isLocalProvider);
yield {
metadata: file,
filepath,
filename: file.hash + file.ext,
stream,
stats: {
size: stats.size
}
};
if (file.formats) {
for (const format of Object.keys(file.formats)){
const fileFormat = file.formats[format];
const fileFormatFilepath = isLocalProvider ? join(strapi1.dirs.static.public, fileFormat.url) : fileFormat.url;
const fileFormatStats = await getFileStats(fileFormatFilepath, strapi1, isLocalProvider);
const fileFormatStream = getFileStream(fileFormatFilepath, strapi1, isLocalProvider);
const metadata = {
...fileFormat,
type: format,
id: file.id,
mainHash: file.hash
};
yield {
metadata,
filepath: fileFormatFilepath,
filename: fileFormat.hash + fileFormat.ext,
stream: fileFormatStream,
stats: {
size: fileFormatStats.size
}
};
}
}
}
};
return Duplex.from(generator());
};
export { createAssetsStream };
//# sourceMappingURL=assets.mjs.map