feat(api): allow bulk uploading (#97)
This commit is contained in:
parent
771cc380df
commit
5c980c21e5
3 changed files with 44 additions and 29 deletions
|
@ -8,19 +8,21 @@ import Alert from 'components/Alert';
|
|||
import { useStoreSelector } from 'lib/redux/store';
|
||||
import CenteredBox from 'components/CenteredBox';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import Link from 'components/Link';
|
||||
|
||||
export default function Upload({ route }) {
|
||||
const user = useStoreSelector(state => state.user);
|
||||
|
||||
const [file, setFile] = useState(null);
|
||||
const [files, setFiles] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [severity, setSeverity] = useState('success');
|
||||
const [message, setMessage] = useState('Saved');
|
||||
|
||||
console.log(files);
|
||||
const handleUpload = async () => {
|
||||
const body = new FormData();
|
||||
body.append('file', file);
|
||||
|
||||
for (let i = 0; i !== files.length; ++i) body.append('file', files[i]);
|
||||
|
||||
setLoading(true);
|
||||
const res = await fetch('/api/upload', {
|
||||
|
@ -34,8 +36,11 @@ export default function Upload({ route }) {
|
|||
if (res.ok && json.error === undefined) {
|
||||
setOpen(true);
|
||||
setSeverity('success');
|
||||
setMessage(`Copied to clipboard! ${json.url}`);
|
||||
|
||||
//@ts-ignore
|
||||
setMessage(<>Copied first image to clipboard! <br/>{json.files.map(x => (<Link key={x} href={x}>{x}<br/></Link>))}</>);
|
||||
copy(json.url);
|
||||
setFiles([]);
|
||||
} else {
|
||||
setOpen(true);
|
||||
setSeverity('error');
|
||||
|
@ -50,7 +55,7 @@ export default function Upload({ route }) {
|
|||
<Alert open={open} setOpen={setOpen} message={message} severity={severity} />
|
||||
|
||||
<Typography variant='h4' pb={2}>Upload file</Typography>
|
||||
<Dropzone onDrop={acceptedFiles => setFile(acceptedFiles[0])}>
|
||||
<Dropzone onDrop={acceptedFiles => setFiles([...files, ...acceptedFiles])}>
|
||||
{({getRootProps, getInputProps}) => (
|
||||
<CardActionArea>
|
||||
<Paper
|
||||
|
@ -67,7 +72,9 @@ export default function Upload({ route }) {
|
|||
<input {...getInputProps()} />
|
||||
<CenteredBox><UploadIcon sx={{ fontSize: 100 }} /></CenteredBox>
|
||||
<CenteredBox><Typography variant='h5'>Drag an image or click to upload an image.</Typography></CenteredBox>
|
||||
<CenteredBox><Typography variant='h6'>{file && file.name}</Typography></CenteredBox>
|
||||
{files.map(file => (
|
||||
<CenteredBox key={file.name}><Typography variant='h6'>{file.name}</Typography></CenteredBox>
|
||||
))}
|
||||
</Paper>
|
||||
</CardActionArea>
|
||||
)}
|
||||
|
|
|
@ -30,7 +30,7 @@ export type NextApiReq = NextApiRequest & {
|
|||
} | null | void>;
|
||||
getCookie: (name: string) => string | null;
|
||||
cleanCookie: (name: string) => void;
|
||||
file?: NextApiFile;
|
||||
files?: NextApiFile[];
|
||||
}
|
||||
|
||||
export type NextApiRes = NextApiResponse & {
|
||||
|
|
|
@ -20,33 +20,41 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
token: req.headers.authorization
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (!user) return res.forbid('authorization incorect');
|
||||
if (!req.file) return res.error('no file');
|
||||
if (req.file.size > zconfig.uploader[user.administrator ? 'admin_limit' : 'user_limit']) return res.error('file size too big');
|
||||
if (!req.files) return res.error('no files');
|
||||
if (req.files && req.files.length === 0) return res.error('no files');
|
||||
|
||||
const ext = req.file.originalname.split('.').pop();
|
||||
if (zconfig.uploader.disabled_extentions.includes(ext)) return res.error('disabled extension recieved: ' + ext);
|
||||
const rand = randomChars(zconfig.uploader.length);
|
||||
const files = [];
|
||||
|
||||
let invis;
|
||||
const image = await prisma.image.create({
|
||||
data: {
|
||||
file: `${rand}.${ext}`,
|
||||
mimetype: req.file.mimetype,
|
||||
userId: user.id,
|
||||
embed: !!req.headers.embed
|
||||
}
|
||||
});
|
||||
for (let i = 0; i !== req.files.length; ++i) {
|
||||
const file = req.files[i];
|
||||
if (file.size > zconfig.uploader[user.administrator ? 'admin_limit' : 'user_limit']) return res.error('file size too big');
|
||||
|
||||
if (req.headers.zws) invis = await createInvis(zconfig.uploader.length, image.id);
|
||||
const ext = file.originalname.split('.').pop();
|
||||
if (zconfig.uploader.disabled_extentions.includes(ext)) return res.error('disabled extension recieved: ' + ext);
|
||||
const rand = randomChars(zconfig.uploader.length);
|
||||
|
||||
await writeFile(join(process.cwd(), zconfig.uploader.directory, image.file), req.file.buffer);
|
||||
let invis;
|
||||
const image = await prisma.image.create({
|
||||
data: {
|
||||
file: `${rand}.${ext}`,
|
||||
mimetype: file.mimetype,
|
||||
userId: user.id,
|
||||
embed: !!req.headers.embed
|
||||
}
|
||||
});
|
||||
|
||||
Logger.get('image').info(`User ${user.username} (${user.id}) uploaded an image ${image.file} (${image.id})`);
|
||||
if (req.headers.zws) invis = await createInvis(zconfig.uploader.length, image.id);
|
||||
|
||||
return res.json({
|
||||
url: `${zconfig.core.secure ? 'https' : 'http'}://${req.headers.host}${zconfig.uploader.route}/${invis ? invis.invis : image.file}`
|
||||
});
|
||||
await writeFile(join(process.cwd(), zconfig.uploader.directory, image.file), file.buffer);
|
||||
Logger.get('image').info(`User ${user.username} (${user.id}) uploaded an image ${image.file} (${image.id})`);
|
||||
files.push(`${zconfig.core.secure ? 'https' : 'http'}://${req.headers.host}${zconfig.uploader.route}/${invis ? invis.invis : image.file}`);
|
||||
}
|
||||
|
||||
// url will be deprecated soon
|
||||
return res.json({ files, url: files[0] });
|
||||
}
|
||||
|
||||
function run(middleware: any) {
|
||||
|
@ -60,7 +68,7 @@ function run(middleware: any) {
|
|||
}
|
||||
|
||||
export default async function handlers(req, res) {
|
||||
await run(uploader.single('file'))(req, res);
|
||||
await run(uploader.array('file'))(req, res);
|
||||
|
||||
return withZipline(handler)(req, res);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue