Skip to content

Commit

Permalink
fix: 文件上传
Browse files Browse the repository at this point in the history
  • Loading branch information
besscroft committed Apr 15, 2024
1 parent 2c9b745 commit 8e9b160
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 70 deletions.
4 changes: 1 addition & 3 deletions app/admin/upload/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Card, CardBody, CardHeader } from '@nextui-org/card'
import FileUpload from '~/components/admin/upload/FileUpload'
import { Button } from '@nextui-org/react'
import UploadSelect from '~/components/admin/upload/UploadSelect'

export default async function Upload() {
export default function Upload() {


return (
Expand All @@ -25,7 +24,6 @@ export default async function Upload() {
</CardHeader>
</Card>
<Card className="flex-1">
<UploadSelect />
<CardBody>
<FileUpload />
</CardBody>
Expand Down
17 changes: 17 additions & 0 deletions app/api/v1/alist-storages/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'server-only'
import { fetchAListInfo } from '~/server/lib/query'

export async function GET() {
const findConfig = await fetchAListInfo()
const alistToken = findConfig.find((item) => item.config_key === 'alist_token')?.config_value || '';
const alistUrl = findConfig.find((item) => item.config_key === 'alist_url')?.config_value || '';

const data = await fetch(`${alistUrl}/api/admin/storage/list`, {
method: 'get',
headers: {
'Authorization': alistToken.toString(),
},
}).then(res => res.json())

return Response.json(data)
}
7 changes: 7 additions & 0 deletions app/api/v1/get-tags/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'server-only'
import { fetchTags } from '~/server/lib/query'

export async function GET() {
const data = await fetchTags();
return Response.json(data)
}
174 changes: 161 additions & 13 deletions components/admin/upload/FileUpload.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,89 @@
'use client'

import React from 'react'
import React, {useState} from 'react'
import { InboxOutlined } from '@ant-design/icons'
import type { UploadProps } from 'antd'
import { Upload } from 'antd'
import { toast } from 'sonner'
import useSWR from 'swr'
import { fetcher } from '~/utils/fetcher'
import { TagType } from '~/types'
import { Button, Select, SelectItem } from '@nextui-org/react'
import { CardHeader } from '@nextui-org/card'


export default function FileUpload() {
const [alistStorage, setAlistStorage] = useState([])
const [storageSelect, setStorageSelect] = useState(false)
const [storage, setStorage] = useState(new Set([] as string[]))
const [tag, setTag] = useState(new Set([] as string[]))
const [alistMountPath, setAlistMountPath] = useState(new Set([] as string[]))

const { data, error, isLoading } = useSWR('/api/v1/get-tags', fetcher)

async function onBeforeUpload(file: any) {
const storageArray = Array.from(storage)
const tagArray = Array.from(tag)
const alistMountPathArray = Array.from(alistMountPath)
if (storageArray.length === 0 || storageArray[0] === '') {
toast.warning('请先选择存储!')
file.abort()
} else if (storageArray[0] === 'alist' && (alistMountPathArray.length === 0 || alistMountPathArray[0] === '')) {
toast.warning('请先选择挂载目录!')
file.abort()
} else if (tagArray.length === 0 || tagArray[0] === '') {
toast.warning('请先选择标签!')
file.abort()
} else {
toast.info('正在上传文件!')
}
}

async function getAlistStorage() {
if (alistStorage.length > 0) {
setStorageSelect(true)
return
}
try {
toast.info('正在获取 AList 挂载目录!')
const res = await fetch('/api/v1/alist-storages', {
method: 'GET',
}).then(res => res.json())
if (res?.code === 200) {
setAlistStorage(res.data?.content)
setStorageSelect(true)
} else {
toast.error('AList 挂载目录获取失败!')
}
} catch (e) {
toast.error('AList 挂载目录获取失败!')
}
}

const storages = [
{
label: 'S3',
value: 's3',
},
{
label: 'AList',
value: 'alist',
}
]

const { Dragger } = Upload;

async function onRequestUpload(option: any) {
const storageArray = Array.from(storage)
const tagArray = Array.from(tag)
const alistMountPathArray = Array.from(alistMountPath)

const formData = new FormData()

formData.append('file', option.file)
formData.append('storage', 'alist')
formData.append('type', 'test')
formData.append('mountPath', '/')
formData.append('storage', storageArray[0])
formData.append('type', tagArray[0])
formData.append('mountPath', alistMountPathArray[0])
const data = await fetch('/api/v1/file-upload', {
method: 'POST',
body: formData
Expand All @@ -39,18 +106,99 @@ export default function FileUpload() {
customRequest: (file) => onRequestUpload(file),
onChange: (event) => {
console.log(event)
},
beforeUpload: async (file) => await onBeforeUpload(file),
onRemove: (file) => {
setStorageSelect(false)
setStorage(new Set([] as string[]))
setTag(new Set([] as string[]))
setAlistMountPath(new Set([] as string[]))
}
}

return (
<Dragger {...props}>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text dark:!text-white">点击上传文件或拖拽文件到这里</p>
<p className="ant-upload-hint dark:!text-gray-200">
Vercel 等平台 Free 订阅限制上传大小 6M。
</p>
</Dragger>
<>
<CardHeader className="flex flex-col space-y-1 p-0 pb-1">
<div className="flex w-full justify-between space-x-1">
<Select
isRequired
variant="bordered"
label="存储"
placeholder="请选择存储"
selectedKeys={storage}
onSelectionChange={(keys) => {
const updatedSet = new Set([] as string[]);
updatedSet.add(keys?.currentKey);
setStorage(updatedSet)
if (keys?.currentKey === 'alist') {
getAlistStorage()
} else {
setStorageSelect(false)
}
}}
>
{storages.map((storage) => (
<SelectItem key={storage.value} value={storage.value}>
{storage.label}
</SelectItem>
))}
</Select>
<Select
isRequired
variant="bordered"
label="标签"
placeholder="请选择标签"
isLoading={isLoading}
selectedKeys={tag}
onSelectionChange={(keys) => {
const updatedSet = new Set([] as string[]);
updatedSet.add(keys?.currentKey);
setTag(updatedSet)
}}
>
{data?.map((tag: TagType) => (
<SelectItem key={tag.tag_value} value={tag.tag_value}>
{tag.name}
</SelectItem>
))}
</Select>
</div>
<div className="w-full">
{
storageSelect && alistStorage?.length > 0
?
<Select
isRequired
variant="bordered"
label="目录"
placeholder="请选择Alist目录"
selectedKeys={alistMountPath}
onSelectionChange={(keys) => {
const updatedSet = new Set([] as string[]);
updatedSet.add(keys?.currentKey);
setAlistMountPath(updatedSet)
}}
>
{alistStorage?.map((storage) => (
<SelectItem key={storage?.mount_path} value={storage?.mount_path}>
{storage?.mount_path}
</SelectItem>
))}
</Select>
:
<></>
}
</div>
</CardHeader>
<Dragger {...props}>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text dark:!text-white">点击上传文件或拖拽文件到这里</p>
<p className="ant-upload-hint dark:!text-gray-200">
Vercel 等平台 Free 订阅限制上传大小 6M。
</p>
</Dragger>
</>
)
}
54 changes: 0 additions & 54 deletions components/admin/upload/UploadSelect.tsx

This file was deleted.

10 changes: 10 additions & 0 deletions server/lib/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,13 @@ export async function fetchImagesList() {

return findAll;
}

export async function fetchTags() {
const findAll = await db.tags.findMany({
where: {
del: 0
}
})

return findAll;
}

0 comments on commit 8e9b160

Please sign in to comment.