2023-08-01 21:03:49 -05:00
|
|
|
import {
|
|
|
|
GetObjectCommand,
|
|
|
|
GetObjectCommandInput,
|
|
|
|
S3,
|
|
|
|
} from "@aws-sdk/client-s3";
|
2023-07-01 09:11:39 -05:00
|
|
|
import fs from "fs";
|
|
|
|
import path from "path";
|
|
|
|
import s3Client from "./s3Client";
|
2023-08-01 21:03:49 -05:00
|
|
|
import util from "util";
|
|
|
|
|
|
|
|
type ReturnContentTypes =
|
2023-10-27 23:45:14 -05:00
|
|
|
| "text/plain"
|
2023-08-01 21:03:49 -05:00
|
|
|
| "image/jpeg"
|
|
|
|
| "image/png"
|
2023-10-29 23:50:43 -05:00
|
|
|
| "application/pdf"
|
|
|
|
| "application/json";
|
2023-07-01 09:11:39 -05:00
|
|
|
|
2023-08-10 11:16:44 -05:00
|
|
|
export default async function readFile(filePath: string) {
|
2023-08-01 21:03:49 -05:00
|
|
|
let contentType: ReturnContentTypes;
|
2023-07-01 09:11:39 -05:00
|
|
|
|
|
|
|
if (s3Client) {
|
|
|
|
const bucketParams: GetObjectCommandInput = {
|
2023-11-09 04:41:29 -06:00
|
|
|
Bucket: process.env.SPACES_BUCKET_NAME,
|
2023-07-01 09:11:39 -05:00
|
|
|
Key: filePath,
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
2023-08-01 21:03:49 -05:00
|
|
|
let returnObject:
|
|
|
|
| {
|
|
|
|
file: Buffer | string;
|
|
|
|
contentType: ReturnContentTypes;
|
2023-08-10 11:16:44 -05:00
|
|
|
status: number;
|
2023-08-01 21:03:49 -05:00
|
|
|
}
|
|
|
|
| undefined;
|
|
|
|
|
|
|
|
const headObjectAsync = util.promisify(
|
|
|
|
s3Client.headObject.bind(s3Client)
|
|
|
|
);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await headObjectAsync(bucketParams);
|
|
|
|
} catch (err) {
|
2023-10-27 23:45:14 -05:00
|
|
|
contentType = "text/plain";
|
2023-08-01 21:03:49 -05:00
|
|
|
|
|
|
|
returnObject = {
|
2023-10-27 23:45:14 -05:00
|
|
|
file: "File not found.",
|
2023-08-01 21:03:49 -05:00
|
|
|
contentType,
|
2023-10-27 23:45:14 -05:00
|
|
|
status: 400,
|
2023-08-01 21:03:49 -05:00
|
|
|
};
|
2023-07-01 09:11:39 -05:00
|
|
|
}
|
|
|
|
|
2023-08-01 21:03:49 -05:00
|
|
|
if (!returnObject) {
|
|
|
|
const response = await (s3Client as S3).send(
|
|
|
|
new GetObjectCommand(bucketParams)
|
|
|
|
);
|
|
|
|
const data = await streamToBuffer(response.Body);
|
|
|
|
|
|
|
|
if (filePath.endsWith(".pdf")) {
|
|
|
|
contentType = "application/pdf";
|
|
|
|
} else if (filePath.endsWith(".png")) {
|
|
|
|
contentType = "image/png";
|
2023-10-29 23:50:43 -05:00
|
|
|
} else if (filePath.endsWith("_readability.json")) {
|
|
|
|
contentType = "application/json";
|
2023-08-01 21:03:49 -05:00
|
|
|
} else {
|
|
|
|
// if (filePath.endsWith(".jpg"))
|
|
|
|
contentType = "image/jpeg";
|
|
|
|
}
|
2023-08-10 11:16:44 -05:00
|
|
|
returnObject = { file: data as Buffer, contentType, status: 200 };
|
2023-08-01 21:03:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return returnObject;
|
2023-07-01 09:11:39 -05:00
|
|
|
} catch (err) {
|
2023-08-01 21:03:49 -05:00
|
|
|
console.log("Error:", err);
|
2023-07-01 09:11:39 -05:00
|
|
|
|
2023-10-27 23:45:14 -05:00
|
|
|
contentType = "text/plain";
|
2023-07-01 09:11:39 -05:00
|
|
|
return {
|
2023-10-27 23:45:14 -05:00
|
|
|
file: "An internal occurred, please contact the support team.",
|
2023-07-01 09:11:39 -05:00
|
|
|
contentType,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
} else {
|
2023-07-21 09:17:26 -05:00
|
|
|
const storagePath = process.env.STORAGE_FOLDER || "data";
|
2023-07-01 09:11:39 -05:00
|
|
|
const creationPath = path.join(process.cwd(), storagePath + "/" + filePath);
|
|
|
|
|
2023-08-10 11:16:44 -05:00
|
|
|
if (filePath.endsWith(".pdf")) {
|
2023-07-01 09:11:39 -05:00
|
|
|
contentType = "application/pdf";
|
|
|
|
} else if (filePath.endsWith(".png")) {
|
|
|
|
contentType = "image/png";
|
2023-10-29 23:50:43 -05:00
|
|
|
} else if (filePath.endsWith("_readability.json")) {
|
|
|
|
contentType = "application/json";
|
2023-07-01 09:11:39 -05:00
|
|
|
} else {
|
|
|
|
// if (filePath.endsWith(".jpg"))
|
|
|
|
contentType = "image/jpeg";
|
|
|
|
}
|
|
|
|
|
2023-08-10 11:16:44 -05:00
|
|
|
if (!fs.existsSync(creationPath))
|
|
|
|
return {
|
2023-10-27 23:45:14 -05:00
|
|
|
file: "File not found.",
|
|
|
|
contentType: "text/plain",
|
|
|
|
status: 400,
|
2023-08-10 11:16:44 -05:00
|
|
|
};
|
|
|
|
else {
|
|
|
|
const file = fs.readFileSync(creationPath);
|
|
|
|
return { file, contentType, status: 200 };
|
|
|
|
}
|
2023-07-01 09:11:39 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn the file's body into buffer
|
|
|
|
const streamToBuffer = (stream: any) => {
|
|
|
|
const chunks: any = [];
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
stream.on("data", (chunk: any) => chunks.push(Buffer.from(chunk)));
|
|
|
|
stream.on("error", (err: any) => reject(err));
|
|
|
|
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
|
|
|
});
|
|
|
|
};
|
2023-08-10 11:16:44 -05:00
|
|
|
|
|
|
|
const fileNotFoundTemplate = `<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<title>File not found</title>
|
|
|
|
</head>
|
|
|
|
<body style="margin-left: auto; margin-right: auto; max-width: 500px; padding: 1rem; font-family: sans-serif; background-color: rgb(251, 251, 251);">
|
|
|
|
<h1>File not found</h1>
|
|
|
|
<h2>It is possible that the file you're looking for either doesn't exist or hasn't been created yet.</h2>
|
|
|
|
<h3>Some possible reasons are:</h3>
|
|
|
|
<ul>
|
2023-08-22 17:34:46 -05:00
|
|
|
<li>You are trying to access a file too early, before it has been fully archived. If that's the case, refreshing the page might resolve the issue.</li>
|
2023-08-10 11:16:44 -05:00
|
|
|
<li>The file doesn't exist either because it encountered an error while being archived, or it simply doesn't exist.</li>
|
|
|
|
</ul>
|
|
|
|
</body>
|
|
|
|
</html>`;
|