直接上代碼,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());
}
}
}
然后配置和工具類:
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* 服務(wù)相關(guān)配置
*
*/
@Component
public class ServerConfig {
/**
* 獲取完整的請求路徑,包括:域名,端口,上下文訪問路徑
*
* @return 服務(wù)地址
*/
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;
}
}
}
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) {
// 添加參數(shù)解析器
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全局轉(zhuǎn)化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();
}*/
}
上傳工具類:
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 {
/**
* 根據(jù)文件路徑上傳
*
* @param baseDir 相對應(yīng)用的基目錄
* @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 相對應(yīng)用的基目錄
* @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;
}
常量類?
/**
* 通用常量信息
*
*/
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;
}
}
假如我們項目的路徑是:D:/project/crm/admin,我們這里返回的路徑就是D:/project/crm/admin/upload
2、文件上傳,用到的方法是這個:
/**
* 文件上傳
*
* @param baseDir 相對應(yīng)用的基目錄
* @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);
}
上傳方法就是?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。經(jīng)過拼接之后,我們會發(fā)現(xiàn),圖片上傳的位置是:
D:/project/crm/admin/upload/2025/05/05/1.jpg
返回的url是:http://127.0.0.1:8080/upload/2025/05/05/1.jpg
這樣就可以訪問了。為什么可以訪問呢,是因為我們配置了靜態(tài)資源的映射,具體配置為:
@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,可以正常訪問圖片。文章來源:http://www.zghlxwxcb.cn/news/detail-595919.html
如果你要匿名訪問,需要在token的配置文件中設(shè)置/upload/**不需要token文章來源地址http://www.zghlxwxcb.cn/news/detail-595919.html
到了這里,關(guān)于springboot上傳文件到本地,并且返回一個http訪問路徑的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!