payload
Version:
Node, React, Headless CMS and Application Framework built on Next.js
84 lines (83 loc) • 3.26 kB
JavaScript
// @ts-strict-ignore
import { fileTypeFromFile } from 'file-type';
import fsPromises from 'fs/promises';
import { status as httpStatus } from 'http-status';
import path from 'path';
import { APIError } from '../../errors/APIError.js';
import { checkFileAccess } from '../../uploads/checkFileAccess.js';
import { streamFile } from '../../uploads/fetchAPI-stream-file/index.js';
import { getFileTypeFallback } from '../../uploads/getFileTypeFallback.js';
import { getRequestCollection } from '../../utilities/getRequestEntity.js';
import { headersWithCors } from '../../utilities/headersWithCors.js';
export const getFileHandler = async (req)=>{
const collection = getRequestCollection(req);
const filename = req.routeParams.filename;
if (!collection.config.upload) {
throw new APIError(`This collection is not an upload collection: ${collection.config.slug}`, httpStatus.BAD_REQUEST);
}
const accessResult = await checkFileAccess({
collection,
filename,
req
});
if (accessResult instanceof Response) {
return accessResult;
}
if (collection.config.upload.handlers?.length) {
let customResponse = null;
for (const handler of collection.config.upload.handlers){
customResponse = await handler(req, {
doc: accessResult,
params: {
collection: collection.config.slug,
filename
}
});
}
if (customResponse instanceof Response) {
return customResponse;
}
}
const fileDir = collection.config.upload?.staticDir || collection.config.slug;
const filePath = path.resolve(`${fileDir}/${filename}`);
let stats;
try {
stats = await fsPromises.stat(filePath);
} catch (err) {
if (err.code === 'ENOENT') {
req.payload.logger.error(`File ${filename} for collection ${collection.config.slug} is missing on the disk. Expected path: ${filePath}`);
// Omit going to the routeError handler by returning response instead of
// throwing an error to cut down log noise. The response still matches what you get with APIError to not leak details to the user.
return Response.json({
errors: [
{
message: 'Something went wrong.'
}
]
}, {
headers: headersWithCors({
headers: new Headers(),
req
}),
status: 500
});
}
throw err;
}
const data = streamFile(filePath);
const fileTypeResult = await fileTypeFromFile(filePath) || getFileTypeFallback(filePath);
let headers = new Headers();
headers.set('Content-Type', fileTypeResult.mime);
headers.set('Content-Length', stats.size + '');
headers = collection.config.upload?.modifyResponseHeaders ? collection.config.upload.modifyResponseHeaders({
headers
}) : headers;
return new Response(data, {
headers: headersWithCors({
headers,
req
}),
status: httpStatus.OK
});
};
//# sourceMappingURL=getFile.js.map