赞
踩
直接上代码,controller层代码:
- @RestController
- @RequestMapping("/common")
- public class CommonController {
-
- private static final Logger log = LoggerFactory.getLogger(CommonController.class);
-
- @Resource
- private ServerConfig serverConfig;
-
- private static final String FILE_DELIMETER = ",";
-
- /**
- * 通用上传请求(单个)
- */
- @ApiOperation(value= "通用本地上传请求(单个)")
- @PostMapping("/upload")
- @ResponseBody
- public CommonResponse uploadFile(@RequestPart(name = "file") MultipartFile file) {
- try {
- // 上传文件路径
- String filePath = serverConfig.getProjectPath();
- // 上传并返回新文件名称
- String fileName = FileUploadUtils.upload(filePath, file);
- String url = serverConfig.getUrl() + fileName;
- JSONObject object = JSONUtil.createObj();
- object.putOpt("url", url);
- object.putOpt("fileName", fileName);
- object.putOpt("newFileName", FileUtils.getName(fileName));
- object.putOpt("originalFilename", file.getOriginalFilename());
- return CommonResponse.ok(object);
- } catch (Exception e) {
- return CommonResponse.fail(e.getMessage());
- }
- }
-
- /**
- * 通用上传请求(多个)
- */
- @ApiOperation(value= "通用本地上传请求(多个)")
- @PostMapping("/uploads")
- @ResponseBody
- public CommonResponse uploadFiles(@RequestPart(name = "files") List<MultipartFile> files) {
- try {
- // 上传文件路径
- String filePath = serverConfig.getProjectPath();
- List<String> urls = new ArrayList<String>();
- List<String> fileNames = new ArrayList<String>();
- List<String> newFileNames = new ArrayList<String>();
- List<String> originalFilenames = new ArrayList<String>();
- for (MultipartFile file : files) {
- // 上传并返回新文件名称
- String fileName = FileUploadUtils.upload(filePath, file);
- String url = serverConfig.getUrl() + fileName;
- urls.add(url);
- fileNames.add(fileName);
- newFileNames.add(FileUtils.getName(fileName));
- originalFilenames.add(file.getOriginalFilename());
- }
- JSONObject object = JSONUtil.createObj();
- object.putOpt("urls", StringUtils.join(urls, FILE_DELIMETER));
- object.putOpt("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
- object.putOpt("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
- object.putOpt("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
- return CommonResponse.ok(object);
- } catch (Exception e) {
- return CommonResponse.fail(e.getMessage());
- }
- }
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
然后配置和工具类:
-
- import org.springframework.core.io.ClassPathResource;
- import org.springframework.core.io.Resource;
- import org.springframework.stereotype.Component;
-
- import javax.servlet.http.HttpServletRequest;
-
- /**
- * 服务相关配置
- *
- */
- @Component
- public class ServerConfig {
-
- /**
- * 获取完整的请求路径,包括:域名,端口,上下文访问路径
- *
- * @return 服务地址
- */
- public String getUrl() {
- HttpServletRequest request = ServletUtils.getRequest();
- return getDomain(request);
- }
-
- public static String getDomain(HttpServletRequest request) {
- StringBuffer url = request.getRequestURL();
- String contextPath = request.getServletContext().getContextPath();
- return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
- }
-
- /**
- * 获取项目根路径
- *
- * @return 路径地址
- */
- public String getProjectPath() {
- try {
- Resource resource = new ClassPathResource("");
- String path = resource.getFile().getAbsolutePath();
- path = path.substring(0, path.indexOf("target") - 1);
- return path + Constants.RESOURCE_PREFIX;
- } catch (Exception e) {
- String path = Constants.RESOURCE_PREFIX;
- if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") >= 0) {
- path = "D:" + Constants.RESOURCE_PREFIX;
- }
- return path;
- }
- }
-
- }
-
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- import com.fasterxml.jackson.annotation.JsonInclude;
- import com.fasterxml.jackson.databind.DeserializationFeature;
- import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
- import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
- import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
- import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Import;
- import org.springframework.http.HttpMethod;
- import org.springframework.http.converter.ByteArrayHttpMessageConverter;
- import org.springframework.web.cors.CorsConfiguration;
- import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
- import org.springframework.web.filter.CorsFilter;
- import org.springframework.web.method.support.HandlerMethodArgumentResolver;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
- import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
- import javax.annotation.Resource;
- import java.math.BigInteger;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.List;
-
-
- /**
- * <p>
- * WebMvc配置类
- * </p>
- *
- **/
- @Import({GlobalExceptionHandler.class})
- @Configuration
- public class WebMvcConfig implements WebMvcConfigurer {
-
- @Resource
- private ServerConfig serverConfig;
-
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController(BaseConstant.WEBSOCKET_HTML).setViewName(BaseConstant.WEBSOCKET);
- registry.addViewController(BaseConstant.MAIL_HTML).setViewName(BaseConstant.MAIL);
- }
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler(BaseConstant.DOC_HTML)
- .addResourceLocations(BaseConstant.META_INF_RESOURCES);
- registry.addResourceHandler(BaseConstant.WEBJARS)
- .addResourceLocations(BaseConstant.META_INF_RESOURCES_WEBJARS);
- String filePath = "file:"+serverConfig.getProjectPath();
- if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") >= 0) {
- registry.addResourceHandler("/upload/**").addResourceLocations(filePath);
- }else {
- registry.addResourceHandler("/upload/**").addResourceLocations(filePath);
- }
-
-
- }
-
- @Override
- public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
- // 添加参数解析器
- argumentResolvers.add(new SingleRequestBodyResolver());
- }
-
- /**
- * @param registry
- * @author quzhaodong
- * @date 2020/11/3
- **/
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- }
-
- /**
- * 允许跨域请求
- */
- @Bean
- public CorsFilter corsFilter() {
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration(BaseConstant.STAR_STAR, corsConfig());
- return new CorsFilter(source);
- }
-
- /**
- * <p>
- * Jackson全局转化long类型为String,解决jackson序列化时long类型缺失精度问题
- * </p>
- */
- @Bean
- public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
- Jackson2ObjectMapperBuilderCustomizer customizer = jacksonObjectMapperBuilder -> {
- jacksonObjectMapperBuilder.serializerByType(BigInteger.class, ToStringSerializer.instance);
- // jacksonObjectMapperBuilder.serializerByType(long.class, ToStringSerializer.instance);
- jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance);
- // jacksonObjectMapperBuilder.serializerByType(Long.TYPE, ToStringSerializer.instance);
- //空值 null 进行序列化
- jacksonObjectMapperBuilder.featuresToEnable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
- jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.ALWAYS);
-
- // 指定日期格式
- // 序列化
- jacksonObjectMapperBuilder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
- // 反序列化
- jacksonObjectMapperBuilder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
- };
- return customizer;
- }
-
-
-
-
-
- /**
- * 跨域配置
- */
- private CorsConfiguration corsConfig() {
- CorsConfiguration corsConfiguration = new CorsConfiguration();
- // 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等)
- corsConfiguration.addAllowedOriginPattern(BaseConstant.STAR);
- corsConfiguration.addAllowedHeader(BaseConstant.STAR);
- corsConfiguration.addAllowedMethod(HttpMethod.OPTIONS);
- corsConfiguration.addAllowedMethod(HttpMethod.GET);
- corsConfiguration.addAllowedMethod(HttpMethod.POST);
- corsConfiguration.addAllowedMethod(HttpMethod.PATCH);
- corsConfiguration.addAllowedMethod(HttpMethod.PUT);
- corsConfiguration.addAllowedMethod(HttpMethod.DELETE);
- corsConfiguration.setAllowCredentials(true);
- corsConfiguration.setMaxAge(3600L);
- return corsConfiguration;
- }
-
- @Bean
- public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
- return new ByteArrayHttpMessageConverter();
- }
-
- /*@Bean
- public CustomizationBean getCustomizationBean() {
- return new CustomizationBean();
- }*/
-
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
上传工具类:
- import java.io.File;
- import java.io.IOException;
- import java.nio.file.Paths;
- import java.util.Objects;
-
-
- import org.apache.commons.io.FilenameUtils;
- import org.springframework.web.multipart.MultipartFile;
-
-
- /**
- * 文件上传工具类
- *
- * @author ruoyi
- */
- public class FileUploadUtils {
-
- /**
- * 根据文件路径上传
- *
- * @param baseDir 相对应用的基目录
- * @param file 上传的文件
- * @return 文件名称
- * @throws IOException
- */
- public static final String upload(String baseDir, MultipartFile file) throws IOException {
- try {
- return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
- } catch (Exception e) {
- throw new IOException(e.getMessage(), e);
- }
- }
-
- /**
- * 文件上传
- *
- * @param baseDir 相对应用的基目录
- * @param file 上传的文件
- * @param allowedExtension 上传文件类型
- * @return 返回上传成功的文件名
- * @throws IOException 比如读写文件出错时
- */
- public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) throws IOException {
-
- String fileName = extractFilename(file);
- assertAllowed(file, allowedExtension);
- String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
- file.transferTo(Paths.get(absPath));
- return getPathFileName(fileName);
- }
-
- /**
- * 编码文件名
- */
- public static final String extractFilename(MultipartFile file) {
- return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
- FilenameUtils.getBaseName(file.getOriginalFilename()), SnowFlakeManager.getSnowFlake().nextId(), getExtension(file));
- }
-
- public static final File getAbsoluteFile(String uploadDir, String fileName) {
- File desc = new File(uploadDir + File.separator + fileName);
-
- if (!desc.exists()) {
- if (!desc.getParentFile().exists()) {
- desc.getParentFile().mkdirs();
- }
- }
- return desc;
- }
-
- public static final String getPathFileName(String fileName) {
- return Constants.RESOURCE_PREFIX + fileName;
- // int dirLastIndex = getDefaultBaseDir().length() + 1;
- // String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
- // if (StringUtils.isNotBlank(currentDir)) {
- // return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
- // }
- // return Constants.RESOURCE_PREFIX + "/" + fileName;
- }
-
- /**
- * 文件校验
- *
- * @param file 上传的文件
- * @return
- * @throws ServiceException
- */
- public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
- throws IOException {
- long size = file.getSize();
- String fileName = file.getOriginalFilename();
- String extension = getExtension(file);
- if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
- throw new IOException("不支持文件:" + fileName + "的文件类型!");
- }
- }
-
- /**
- * 判断MIME类型是否是允许的MIME类型
- *
- * @param extension
- * @param allowedExtension
- * @return
- */
- public static final boolean isAllowedExtension(String extension, String[] allowedExtension) {
- for (String str : allowedExtension) {
- if (str.equalsIgnoreCase(extension)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * 获取文件名的后缀
- *
- * @param file 表单文件
- * @return 后缀名
- */
- public static final String getExtension(MultipartFile file) {
- String extension = FilenameUtils.getExtension(file.getOriginalFilename());
- if (StringUtils.isEmpty(extension)) {
- extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
- }
- return extension;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
常量类
- /**
- * 通用常量信息
- *
- */
- public class Constants
- {
-
- /**
- * 资源映射路径 前缀
- */
- public static final String RESOURCE_PREFIX = "/upload/";
-
-
- }
接下来讲一下思路:
1、首先我们是要把文件上传到项目的目录中,获取项目路径的方法是这个:
- /**
- * 获取项目根路径
- *
- * @return 路径地址
- */
- public String getProjectPath() {
- try {
- Resource resource = new ClassPathResource("");
- String path = resource.getFile().getAbsolutePath();
- path = path.substring(0, path.indexOf("target") - 1);
- return path + Constants.RESOURCE_PREFIX;
- } catch (Exception e) {
- String path = Constants.RESOURCE_PREFIX;
- if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") >= 0) {
- path = "D:" + Constants.RESOURCE_PREFIX;
- }
- return path;
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
假如我们项目的路径是:D:/project/crm/admin,我们这里返回的路径就是D:/project/crm/admin/upload
2、文件上传,用到的方法是这个:
- /**
- * 文件上传
- *
- * @param baseDir 相对应用的基目录
- * @param file 上传的文件
- * @param allowedExtension 上传文件类型
- * @return 返回上传成功的文件名
- * @throws IOException 比如读写文件出错时
- */
- public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) throws IOException {
-
- String fileName = extractFilename(file);
- assertAllowed(file, allowedExtension);
- String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
- file.transferTo(Paths.get(absPath));
- return getPathFileName(fileName);
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
上传方法就是 file.transferTo(Paths.get(absPath));
3、然后就是返回一个可以访问的路径,方法是:
- //这里只返回图片的地址,不带项目的url,String url = serverConfig.getUrl() + fileName;
- public static final String getPathFileName(String fileName) {
- return Constants.RESOURCE_PREFIX + fileName;
-
- }
4。经过拼接之后,我们会发现,图片上传的位置是:
D:/project/crm/admin/upload/2025/05/05/1.jpg
返回的url是:http://127.0.0.1:8080/upload/2025/05/05/1.jpg
这样就可以访问了。为什么可以访问呢,是因为我们配置了静态资源的映射,具体配置为:
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler(BaseConstant.DOC_HTML)
- .addResourceLocations(BaseConstant.META_INF_RESOURCES);
- registry.addResourceHandler(BaseConstant.WEBJARS)
- .addResourceLocations(BaseConstant.META_INF_RESOURCES_WEBJARS);
- String filePath = "file:"+serverConfig.getProjectPath();
- if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") >= 0) {
- registry.addResourceHandler("/upload/**").addResourceLocations(filePath);
- }else {
- registry.addResourceHandler("/upload/**").addResourceLocations(filePath);
- }
-
-
- }
这就是将文件上传到本地,并且返回一个url,可以正常访问图片。
如果你要匿名访问,需要在token的配置文件中设置/upload/**不需要token
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。