Skip to content

Commit

Permalink
feat(upload): upload attaches with error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
nyet-ty committed Aug 8, 2023
1 parent f589b65 commit bc8fc43
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 45 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@sentry/nextjs": "7.60.0",
"@tanstack/react-query": "4.29.5",
"@tanstack/react-query-devtools": "4.29.5",
"@taskany/bricks": "1.28.0",
"@taskany/bricks": "1.29.0",
"@taskany/colors": "1.1.0",
"@taskany/icons": "1.0.0",
"@tippyjs/react": "4.2.6",
Expand Down
86 changes: 49 additions & 37 deletions src/pages/api/upload.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-await-in-loop */
import nextConnect from 'next-connect';
import crypto from 'crypto';
import multer from 'multer';
Expand All @@ -23,6 +24,12 @@ const cors = Cors({
methods: ['HEAD', 'OPTIONS', 'POST'],
});

type ResponseObj = {
failed: string[];
succeeded: string[];
errorMessage?: string;
};

const upload = multer({ storage: multer.memoryStorage() });

const route = nextConnect({
Expand Down Expand Up @@ -55,43 +62,48 @@ route.post(upload.array(formFieldName, 10), async (req: any, res: NextApiRespons
region: process.env.S3_REGION,
});
}

const result = await Promise.all(
req[formFieldName].map(
async ({ originalname, mimetype, buffer }: { originalname: string; mimetype: string; buffer: Buffer }) => {
// @ts-ignore Translit is any ¯\_(ツ)_/¯
let fileName = new Translit({ preset: 'ru' }).transform(originalname, '_');

if (JSON.parse(uniqueNames)) {
const hashSum = crypto.createHash('sha256');
hashSum.update(buffer);
const hex = hashSum.digest('hex');

fileName = `${hex.slice(0, 8)}_${fileName}`;
}

if (!s3Client) {
return saveFileInPublic(fileName, buffer);
}

return Promise.resolve(
s3Client.send(
new PutObjectCommand({
Bucket: process.env.S3_BUCKET,
BucketKeyEnabled: false,
Key: `${folder}/${fileName}`,
Body: buffer,
ACL: 'authenticated-read',
CacheControl: 'max-age=630720000, public',
ContentType: mimetype,
}),
),
).then(() => `${process.env.PUBLIC_URL}/static/${folder}/${fileName}`);
},
),
);

res.status(200).json(result);
const resultObject: ResponseObj = {
failed: [],
succeeded: [],
};

for (const file of req[formFieldName]) {
const { originalname, mimetype, buffer } = file;
// @ts-ignore Translit is any ¯\_(ツ)_/¯
let fileName = new Translit({ preset: 'ru' }).transform(originalname, '_');

if (JSON.parse(uniqueNames)) {
const hashSum = crypto.createHash('sha256');
hashSum.update(buffer);
const hex = hashSum.digest('hex');

fileName = `${hex.slice(0, 8)}_${fileName}`;
}

if (!s3Client) {
const filePath = await saveFileInPublic(fileName, buffer);
resultObject.succeeded.push(filePath);
} else {
await s3Client
.send(
new PutObjectCommand({
Bucket: process.env.S3_BUCKET,
BucketKeyEnabled: false,
Key: `${folder}/${fileName}`,
Body: buffer,
ACL: 'authenticated-read',
CacheControl: 'max-age=630720000, public',
ContentType: mimetype,
}),
)
.then(() => resultObject.succeeded.push(`${process.env.PUBLIC_URL}/static/${folder}/${fileName}`))
.catch((error) => {
resultObject.failed.push(originalname);
resultObject.errorMessage = error.message;
});
}
}
res.status(200).json(resultObject);
});

export default route;

0 comments on commit bc8fc43

Please sign in to comment.