springboot + react(antd)文件上传与下载
后台
-
依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--swagger--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.9</version> </dependency>
-
yml配置
# 应用名称 spring: application: name: file-io # 应用服务 WEB 访问端口 server: port: 8080 file: # 自定义文件上传路径 winPath: d:/sbfzl/ # windows下上传路径 unixPath: ~/sbfzl/ # 类unix系统下盛传路径 profile: /images/** # 资源映射
-
配置类
-
file配置
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "file") @Data public class FileProperties { private String winPath; private String unixPath; private String profile; public String getPath() { String os = System.getProperty("os.name"); if (os.toLowerCase().startsWith("win")) { return winPath; }else { return unixPath; } } }
-
跨域配置
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") .allowCredentials(true) .maxAge(3600) .allowedHeaders("*"); } }
-
配置资源映射
import com.example.fileio.config.properties.FileProperties; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; @Configuration public class WebConfig implements WebMvcConfigurer { @Resource private FileProperties fileProperties; /** * 映射文件地址 * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(fileProperties.getProfile()).addResourceLocations("file:"+ fileProperties.getPath()); } }
-
-
资源上传接口实现类
import com.example.fileio.config.properties.FileProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.File; import java.io.IOException; import java.util.UUID; @Service @Slf4j public class FileServiceImpl implements FileService{ @Resource private FileProperties fileProperties; @Override public String upload(MultipartFile file) { String uploadPath = fileProperties.getPath(); log.info("path: {}", uploadPath); try { File path = new File(uploadPath).getCanonicalFile(); if(!path.exists()){ path.mkdirs(); } String oriName = file.getOriginalFilename(); String fileName = UUID.randomUUID().toString().substring(0, 18) + oriName.substring(oriName.lastIndexOf(".")); File descFile = new File(path.getAbsolutePath() + "/" + fileName); file.transferTo(descFile); return fileName; } catch (IOException e) { e.printStackTrace(); return "failure"; } } }
-
controller
import com.example.fileio.service.FileService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; @RequestMapping("file") @Slf4j @RestController @RequiredArgsConstructor public class DemoController { private final FileService fileService; @PostMapping("upload") public Map<String, Object> upload(@RequestPart MultipartFile file) { String name = fileService.upload(file); Map<String, Object> res = new HashMap<>(); res.put("res", name); return res; } }
前端
依赖
"dependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/pro-components": "^1.1.3",
"@umijs/max": "^4.0.7",
"antd": "^4.20.7"
},
"devDependencies": {
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"typescript": "^4.1.2"
}
页面
import { InboxOutlined, LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { FooterToolbar, PageContainer, ProForm, ProFormDateRangePicker, ProFormDigit, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea, ProFormUploadButton } from '@ant-design/pro-components';
import { Card, Form, message, Upload } from 'antd';
import { RcFile } from 'antd/lib/upload';
import { useState } from 'react';
import styles from './index.less';
function HomePage() {
const [imageUrl, setImageUrl] = useState<string>();
const [loading, setLoading] = useState(false);
async function submit(val: Record<string, any>) {
console.log('val', val)
}
const beforeUpload = (file: RcFile) => {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
};
const normFile = (e: any) => {
console.log('Upload event:', e);
if (Array.isArray(e)) {
return e;
}
const res = e?.file?.response?.res
if (res && res.length > 0) {
setImageUrl('http://localhost:8080/images/' + res)
setLoading(false)
}
return res;
};
const uploadButton = (
<div>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
<div style={{ marginTop: 8 }}>Upload</div>
</div>
);
return (
<PageContainer ghost>
<div className={styles.container}>
<Card>
<ProForm
submitter={{
render: (_, dom) => <FooterToolbar>{dom}</FooterToolbar>,
}}
onFinish={submit}
>
<Form.Item name="filename" valuePropName="res" getValueFromEvent={normFile} noStyle>
<Upload
name="file"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="http://localhost:8080/file/upload"
beforeUpload={beforeUpload}
>
{imageUrl ? <img src={imageUrl} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
</Upload>
</Form.Item>
</ProForm>
</Card>
</div>
</PageContainer>
);
};
export default HomePage;
本文作者:七つ一旋桜
本文链接:https://www.cnblogs.com/poifa/p/16500420.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步