Skip to content

Commit

Permalink
Merge pull request #15 from TuringCup/feature_backend
Browse files Browse the repository at this point in the history
胡乱完成了项目,目前可以上传了
  • Loading branch information
deltaLRD authored Oct 13, 2023
2 parents 31ccd8c + b2cdc05 commit aa04f11
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 33 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@
"axios": "^1.5.1",
"eslint": "8.45.0",
"eslint-config-next": "13.4.10",
"formidable": "v3",
"next": "13.4.10",
"postcss": "8.4.26",
"react": "18.2.0",
"react-dom": "18.2.0",
"swr": "^2.2.4",
"tailwindcss": "3.3.3",
"typescript": "5.1.6"
},
"devDependencies": {
"@types/formidable": "^3.4.3"
}
}
44 changes: 34 additions & 10 deletions src/app/route.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
import {NextRequest} from "next/server";
import {NextResponse} from "next/server";

export async function GET(req: NextRequest){
if(!req.cookies.has("token")) {
const url = req.nextUrl.clone()
url.pathname = '/user/login'
return NextResponse.redirect(url)
}else{
const url = req.nextUrl.clone()
url.pathname = '/user/upload'
return NextResponse.redirect(url)
export async function GET(req: NextRequest) {
try {
if (!req.cookies.has("token")) {
const url = req.nextUrl.clone()
url.pathname = '/user/login'
return NextResponse.redirect(url)
} else {

let reqBody = new FormData();
let token = req.cookies.get("token")?.value;
reqBody.append("token", token as string);

let api_response = await fetch("http://49.234.15.205:5001/api/validtoken", {
method: "POST",
body: reqBody
}).then(e => e.json()) as {
errorCode: number,
errorMsg: string
};

if (api_response.errorCode === 200) {
const url = req.nextUrl.clone()
url.pathname = '/user/upload'
return NextResponse.redirect(url)
} else {
const url = req.nextUrl.clone()
url.pathname = '/user/login'
return NextResponse.redirect(url)
}
}
} catch (e) {
console.error(e);
return NextResponse.redirect("/504");
}
}
}
15 changes: 12 additions & 3 deletions src/app/user/api-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ interface RegisterResponse {



export const api = {
const api = {
i: 0,
useLogin( condition: boolean, request : LoginRequest ) {
return useSWR(condition ? "/api/user/login?id=" + api.i : null, async(path) => {
return fetch("/api/api-proxy", {
return fetch("/api/apiProxy", {
method: "POST",
body: JSON.stringify(
{
Expand Down Expand Up @@ -78,7 +78,7 @@ export const api = {

useRegister( condition: boolean, request : RegisterRequest ) {
return useSWR(condition ? "/api/user/register?id=" + api.i : null, async(path) => {
return fetch("/api/api-proxy", {
return fetch("/api/apiProxy", {
method: "POST",
body: JSON.stringify(
{
Expand All @@ -102,6 +102,15 @@ export const api = {
},{
refreshInterval: 1000
})
},

async verifyToken(token: string) {
const e = await fetch("/api/verifyToken", {
method: "POST"
});
const e_1 = await e.json() as APIResponse<any>;
return e_1.success && e_1.response.errorCode == 200;
}
};

export {api};
6 changes: 3 additions & 3 deletions src/app/user/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ const divStyle = {


export default function Page() {
useEffect(() => {
document.cookie = "";
}, []);
// useEffect(() => {
// document.cookie = "";
// }, []);

const [changed, setChanged] = useState(false);
const [usernameValue, setUserName] = useState("");
Expand Down
7 changes: 4 additions & 3 deletions src/app/user/upload/UploadFileBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
import {ChangeEvent} from "react";

const VisuallyHiddenInput = styled('input')({
clip: 'rect(0 0 0 0)',
Expand All @@ -17,14 +18,14 @@ const VisuallyHiddenInput = styled('input')({

interface UploadFileBtnPops{
text: string,

onChange: (e: ChangeEvent<HTMLInputElement>)=>void
}

export default React.forwardRef(function UploadFileBtn({ text }: UploadFileBtnPops, ref: React.Ref<HTMLInputElement>) {
export default React.forwardRef(function UploadFileBtn({ text, onChange }: UploadFileBtnPops, ref: React.Ref<HTMLInputElement>) {
return (
<Button component="label" variant="contained" startIcon={<CloudUploadIcon />}>
{text}
<VisuallyHiddenInput type="file" ref={ref} />
<VisuallyHiddenInput type="file" ref={ref} onChange={onChange}/>
</Button>
);
});
130 changes: 119 additions & 11 deletions src/app/user/upload/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
"use client";
import {Box, Button, FormControl, Paper as MuiPaper, Typography, styled} from "@mui/material";
import {Box, Button, FormControl, Paper as MuiPaper, Typography, styled, Alert} from "@mui/material";
import {config} from "@/config/config";
import UploadFileBtn from "@/app/user/upload/UploadFileBtn";
import {useEffect, useRef} from "react";
import {ChangeEvent, useEffect, useRef, useState} from "react";
import {redirect} from "next/navigation";
import {api} from "@/app/user/api-request";
import {File} from "buffer";

const Paper = styled(MuiPaper)({
minWidth: "36rem",
Expand All @@ -24,26 +27,131 @@ const divStyle = {
justifyContent: "center",
alignItems: "center",
};
export default function Page(){
export default function Page() {
const ref = useRef<HTMLInputElement>(null);
useEffect(()=>{
if(ref.current){
console.log(ref.current);
ref.current.addEventListener("change", (e)=>{
console.log(ref.current?.value)
const [uploadState, setUploadState] = useState({
upload:false,
ok: true,
msg: ""
});
useCookieTokenVerify();

let onChange = (e: ChangeEvent<HTMLInputElement>) =>{
upload_file(e.target as HTMLInputElement, (ok, msg) => {
setUploadState({
upload: true,
ok,
msg
});
});
e.target.value = "";
};


let status = <>
{
(() => {
if (uploadState.upload) {

if (!uploadState.ok) {
return <Alert severity={"error"}>{uploadState.msg}</Alert>;
}

return <Alert severity={"success"}>{uploadState.msg}</Alert>;
}
return "";
})()
}
},[ref.current]);
</>;

return <>
<Box sx={divStyle}>
<Paper elevation={24}>
<Typography variant={"h3"} gutterBottom>
{config.upload.Upload}
</Typography>
<FormControl sx={{ m: 1, minWidth: "12rem" }}>
<UploadFileBtn text={config.upload.Upload} ref={ref}></UploadFileBtn>
<FormControl sx={{m: 1, minWidth: "12rem"}}>
<UploadFileBtn text={config.upload.Upload} ref={ref} onChange={onChange}></UploadFileBtn>
</FormControl>
<br/>
{status}
</Paper>
</Box>
</>;
}

function upload_file(input: HTMLInputElement, setUploadState: (ok:boolean, msg: string)=>void) {
if (input.files == null)
return;

if (input.files.length == 0)
return;

if(!confirm(config.upload.UploadConfirm.replace("{}", input.value))){
return;
}

let value = input.files.item(0);
if (value) {
let form = new FormData();
form.append("file", value);
value.arrayBuffer().then(file => {
fetch("/api/uploadFile?name=" + value?.name, {
method: "POST",
body: form
}).then(e => e.json())
.then(e => e.response)
.then(e => e.errorCode == 200 ? setUploadState(true, e.errorMsg) : setUploadState(false, e.errorMsg))
.catch(e => setUploadState(false, e.toString()))
}
);
}
}


function useCookieTokenVerify() {
useEffect(() => {
let interval = setInterval(() => {
let result = getCookie("token");
if (result != null) {
api.verifyToken(result).then(e => {
if (!e) {
clearInterval(interval);
alert("登录过期,请重新登录");
delCookie("token")
document.cookie = "";
window.location.href = "/";
}
}).catch(e => {
console.error(e)
});
} else {
clearInterval(interval);
alert("登录过期,请重新登录");
delCookie("token")
window.location.href = "/";
}
}, 2000);

return () => clearInterval(interval);
}, []);
}


function getCookie(name: string) {
let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if ((arr = document.cookie.match(reg)) !== null) {
return unescape(arr[2]);
} else {
return null;
}
}

function delCookie(name: string) {
let exp = new Date();
exp.setTime(exp.getTime() - 1);
let cval = getCookie(name);
if (cval != null) {
document.cookie = name + "=" + cval + ";expires=" + (exp as any).toGMTString() + "; path=/";
}
}
1 change: 1 addition & 0 deletions src/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const config = {
},
upload:{
Upload: "上传",
UploadConfirm: "您确认要上传{}吗?"
}
};

Expand Down
9 changes: 6 additions & 3 deletions src/pages/api/api-proxy.ts → src/pages/api/apiProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ type ResponseData = {
const allow_paths = [
"/api/user/register",
"/api/user/login",
"/api/user/upload"
"/api/user/upload",
"/api/validtoken"
]

const host = "http://49.234.15.205:5001";
Expand Down Expand Up @@ -53,9 +54,10 @@ export default async function handler(
for(let i in request.data as any){
formData.append(i, (request.data as any)[i])
}
console.log(request)
let data = await axios.request({
url: `${host}${request.path}`,
method: request.method?.toLowerCase(),
method: request.method?.toUpperCase(),
data: formData,
});
let api_data = await data.data as object;
Expand All @@ -69,4 +71,5 @@ export default async function handler(
response: "Exception occurred: " + e.toString()
})
}
}
}

54 changes: 54 additions & 0 deletions src/pages/api/uploadFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {NextApiRequest, NextApiResponse} from "next";
import {formidable} from "formidable";
import {readFileSync} from "fs";

type ResponseData = {
success: boolean,
response: string, // 当且仅当success是false的时候才是string
}

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
if (req.method?.toLowerCase() !== "post") {
res.status(404).redirect("/404");
return;
}

try {
let [,{file: files}] = await formidable().parse(req,);
if(files == undefined){
throw "No file uploaded";
}
let file = files[0];
let file_data = new Blob([readFileSync(file.filepath)]);
let reqBody = new FormData();
let token = req.cookies["token"];
reqBody.append("token", token as string);
reqBody.append("file", file_data, req.query["name"] as string | undefined ?? "upload.zip");

let api_response = await fetch("http://49.234.15.205:5001/api/user/upload", {
method: "POST",
body: reqBody
}).then(e => e.json()) as {
};

res.status(200).json({
success: true,
response: api_response as any
})

} catch (e: any) {
res.status(200).json({
success: false,
response: "Exception occurred: " + e.toString()
})
}
}

export const config = {
api: {
bodyParser: false
}
}
Loading

0 comments on commit aa04f11

Please sign in to comment.