mirror of
https://github.com/directus/directus.git
synced 2026-01-24 18:38:08 -05:00
Return file info after successful upload
This commit is contained in:
@@ -3,8 +3,6 @@ import asyncHandler from 'express-async-handler';
|
||||
import Busboy from 'busboy';
|
||||
import sanitizeQuery from '../middleware/sanitize-query';
|
||||
import * as FilesService from '../services/files';
|
||||
import logger from '../logger';
|
||||
import { InvalidPayloadException } from '../exceptions';
|
||||
import useCollection from '../middleware/use-collection';
|
||||
import { Item } from '../types';
|
||||
|
||||
@@ -17,14 +15,23 @@ const multipartHandler = (operation: 'create' | 'update') =>
|
||||
const busboy = new Busboy({ headers: req.headers });
|
||||
const savedFiles: Item[] = [];
|
||||
|
||||
const accountability = {
|
||||
role: req.role,
|
||||
admin: req.admin,
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent'),
|
||||
user: req.user,
|
||||
};
|
||||
|
||||
/**
|
||||
* The order of the fields in multipart/form-data is important. We require that all fields
|
||||
* are provided _before_ the files. This allows us to set the storage location, and create
|
||||
* the row in directus_files async during the upload of the actual file.
|
||||
*/
|
||||
|
||||
let disk: string;
|
||||
let disk: string = (process.env.STORAGE_LOCATIONS as string).split(',')[0].trim();
|
||||
let payload: Partial<Item> = {};
|
||||
let fileCount = 0;
|
||||
|
||||
busboy.on('field', (fieldname, val) => {
|
||||
if (fieldname === 'storage') {
|
||||
@@ -35,9 +42,7 @@ const multipartHandler = (operation: 'create' | 'update') =>
|
||||
});
|
||||
|
||||
busboy.on('file', async (fieldname, fileStream, filename, encoding, mimetype) => {
|
||||
if (!disk) {
|
||||
return busboy.emit('error', new InvalidPayloadException('No storage provided.'));
|
||||
}
|
||||
fileCount++;
|
||||
|
||||
payload = {
|
||||
...payload,
|
||||
@@ -46,48 +51,40 @@ const multipartHandler = (operation: 'create' | 'update') =>
|
||||
type: mimetype,
|
||||
};
|
||||
|
||||
if (!payload.storage) {
|
||||
payload.storage = disk;
|
||||
}
|
||||
|
||||
if (req.user) {
|
||||
payload.uploaded_by = req.user;
|
||||
}
|
||||
|
||||
fileStream.on('end', () => {
|
||||
logger.info(`File ${filename} uploaded to ${disk}.`);
|
||||
});
|
||||
|
||||
try {
|
||||
if (operation === 'create') {
|
||||
const pk = await FilesService.createFile(payload, fileStream, {
|
||||
role: req.role,
|
||||
admin: req.admin,
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent'),
|
||||
user: req.user,
|
||||
});
|
||||
const file = await FilesService.readFile(pk, req.sanitizedQuery, {
|
||||
role: req.role,
|
||||
admin: req.admin,
|
||||
});
|
||||
const pk = await FilesService.createFile(payload, fileStream, accountability);
|
||||
const file = await FilesService.readFile(
|
||||
pk,
|
||||
req.sanitizedQuery,
|
||||
accountability
|
||||
);
|
||||
|
||||
savedFiles.push(file);
|
||||
tryDone();
|
||||
} else {
|
||||
const pk = await FilesService.updateFile(
|
||||
req.params.pk,
|
||||
payload,
|
||||
{
|
||||
role: req.role,
|
||||
admin: req.admin,
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent'),
|
||||
user: req.user,
|
||||
},
|
||||
accountability,
|
||||
fileStream
|
||||
);
|
||||
const file = await FilesService.readFile(pk, req.sanitizedQuery, {
|
||||
role: req.role,
|
||||
admin: req.admin,
|
||||
});
|
||||
const file = await FilesService.readFile(
|
||||
pk,
|
||||
req.sanitizedQuery,
|
||||
accountability
|
||||
);
|
||||
|
||||
savedFiles.push(file);
|
||||
tryDone();
|
||||
}
|
||||
} catch (err) {
|
||||
busboy.emit('error', err);
|
||||
@@ -99,10 +96,20 @@ const multipartHandler = (operation: 'create' | 'update') =>
|
||||
});
|
||||
|
||||
busboy.on('finish', () => {
|
||||
res.status(200).json({ data: savedFiles || null });
|
||||
tryDone();
|
||||
});
|
||||
|
||||
return req.pipe(busboy);
|
||||
req.pipe(busboy);
|
||||
|
||||
function tryDone() {
|
||||
if (savedFiles.length === fileCount) {
|
||||
if (fileCount === 1) {
|
||||
return res.status(200).json({ data: savedFiles[0] });
|
||||
} else {
|
||||
return res.status(200).json({ data: savedFiles });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/', sanitizeQuery, multipartHandler('create'));
|
||||
|
||||
@@ -52,8 +52,11 @@ export const createFile = async (
|
||||
});
|
||||
}
|
||||
|
||||
const pk = await ItemsService.createItem('directus_files', payload, accountability);
|
||||
|
||||
await storage.disk(data.storage).put(payload.filename_disk, stream.pipe(pipeline));
|
||||
return await ItemsService.createItem('directus_files', payload, accountability);
|
||||
|
||||
return pk;
|
||||
};
|
||||
|
||||
export const readFiles = async (query: Query, accountability?: Accountability) => {
|
||||
|
||||
@@ -99,6 +99,16 @@ export async function processValues(
|
||||
})
|
||||
);
|
||||
|
||||
if (['create', 'update'].includes(operation)) {
|
||||
processedPayload.forEach((record) => {
|
||||
for (const [key, value] of Object.entries(record)) {
|
||||
if (Array.isArray(value) || (typeof value === 'object' && value !== null)) {
|
||||
record[key] = JSON.stringify(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(payload)) {
|
||||
return processedPayload;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user