strapi-provider-upload-linode
Version:
Linode S3 object storage provider for Strapi upload plugin
129 lines (115 loc) • 3.31 kB
JavaScript
;
const AWS = require("aws-sdk");
const URI = require("urijs");
const crypto = require("crypto");
class FileLocationConverter {
constructor(config) {
this.config = config;
}
getKey(file) {
const filename = `${file.hash}${file.ext}`;
if (!this.config.directory) return filename;
return `${this.config.directory}/${filename}`;
}
getUrl(data) {
if (!this.config.cdn) return data.Location;
var parts = {};
URI.parseHost(this.config.cdn, parts);
parts.protocol = "https"; // Force https
parts.path = data.Key;
return URI.build(parts);
}
}
module.exports = {
provider: "li-s3",
name: "Linode object Storage",
auth: {
key: {
label: "Key",
type: "text",
},
secret: {
label: "Secret",
type: "text",
},
endpoint: {
label: "Endpoint (e.g. 'api.linode.com/v4/object-storage/buckets/')",
type: "text",
},
cdn: {
label: "CDN Endpoint (Optional - e.g. 'https://cdn.space.com')",
type: "text",
},
space: {
label: "Space (e.g. myspace)",
type: "text",
},
directory: {
label:
"Directory (Optional - e.g. directory - place when you want to save files)",
type: "text",
},
},
init: (config) => {
const endpoint = new AWS.Endpoint(config.endpoint);
const converter = new FileLocationConverter(config);
const S3 = new AWS.S3({
endpoint: endpoint,
accessKeyId: config.key,
secretAccessKey: config.secret,
params: {
ACL: "public-read",
Bucket: config.space,
CacheControl: "public, max-age=31536000, immutable",
},
});
const upload = (file) =>
new Promise((resolve, reject) => {
//--- Compute the file key.
file.hash = crypto.createHash("md5").update(file.hash).digest("hex");
//--- Upload the file into the space (technically the S3 Bucket)
S3.upload(
{
Key: converter.getKey(file),
Body: Buffer.from(file.buffer, "binary"),
ContentType: file.mime,
},
//--- Callback handler
(err, data) => {
if (err) return reject(err);
file.url = converter.getUrl(data);
delete file.buffer;
resolve();
}
);
});
return {
upload,
uploadStream: (file) =>
new Promise((resolve, reject) => {
const _buf = [];
file.stream.on("data", (chunk) => _buf.push(chunk));
file.stream.on("end", () => {
file.buffer = Buffer.concat(_buf);
resolve(upload(file));
});
file.stream.on("error", (err) => reject(err));
}),
delete: (file) =>
new Promise((resolve, reject) => {
//--- Delete the file from the space
S3.deleteObject(
{
Bucket: config.bucket,
Key: converter.getKey(file),
},
//--- Callback handler
(err, data) => {
if (err) return reject(err);
else resolve();
}
);
}),
};
},
};