java后端项目映射本地附件方法,以及访问资源链接出现中文乱码解决办法
前言
在项目中,通过文件上传组件完成附件资源存储工作,上传到指定目录进行管理,通过本地资源映射方式完成资源读取工作
一、如何进行资源映射
1、创建配置类
代码如下:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.util.unit.DataSize;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.MultipartConfigElement;
@Configuration
@SuppressWarnings("deprecation")
public class WebAppConfig implements WebMvcConfigurer {
/**
* 在配置文件中配置的文件保存路径
*/
@Value("${cbs.imagesPath}")
private String mImagesPath;
private String suffix = ".jar";
private String classes = "classes";
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
//文件最大KB,MB
factory.setMaxFileSize(DataSize.parse("1024MB"));
//设置总上传数据总大小
factory.setMaxRequestSize(DataSize.parse("1024MB"));
return factory.createMultipartConfig();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!StringUtils.hasLength(mImagesPath)) {
String imagesPath = WebAppConfig.class.getClassLoader().getResource("").getPath();
System.out.print("1.上传配置类imagesPath==" + imagesPath + "\n");
if (imagesPath.indexOf(suffix) > 0) {
imagesPath = imagesPath.substring(0, imagesPath.indexOf(".jar"));
} else if (imagesPath.indexOf(classes) > 0) {
imagesPath = "file:" + imagesPath.substring(0, imagesPath.indexOf("classes"));
}
imagesPath = imagesPath.substring(0, imagesPath.lastIndexOf("/")) + "/images/";
mImagesPath = imagesPath;
}
System.out.print("imagesPath=============" + mImagesPath + "\n");
/**LoggerFactory.getLogger(WebAppConfig.class).info("imagesPath============="+mImagesPath+"\n");*/
registry.addResourceHandler("/images/**").addResourceLocations(mImagesPath);
// TODO Auto-generated method stub
System.out.print("2.上传配置类mImagesPath==" + mImagesPath + "\n");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
}
// application.properties
#配置外部访问文件(把上传的图片视频文件放到E盘下的myUpload文件夹下)
cbs.imagesPath=file:/E:/myUpload/
代码解释:
1、@SuppressWarnings(“deprecation”)表示不检测过期的方法
2、@Value("${cbs.imagesPath}") application配置文件中的自定义的文件路径
二、测试使用
成功运行项目之后,在本地E:/myUpload/下存放需要测试的附件资源,通过http://ip:端口/images/附件资源名称
e.g
二访问资源链接出现中文乱码解决办法
情况1:访问目录下的某一带有中文、特殊字符的资源时,报404
原因在于SpringBoot2.6版本之后修改了映射请求处理的默认策略,由原来的AntPathMatcher更改为PathPatternParser
解决方案
// 第一种:在WebMvcConfig中关闭decode
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/*更改程序映射请求路径默认策略*/
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper=new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
urlPathHelper.setDefaultEncoding(StandardCharsets.UTF_8.name());
configurer.setUrlPathHelper(urlPathHelper);
}
}
// 第二种:在properties或yaml中,更改springboot2.6之后的默认程序映射请求策略
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
情况2:访问目录下的某一带有中文、特殊字符的资源时,报400
URL编码及解码原理:
由于我们利用URL传递参数这种方式是依赖与浏览器环境中的,也就是说URL及URL中包含的各个格式的传递参数是在浏览器地址栏中的处理原理处理相应编码后传递至后台进行解码的。
由于我们没有进行任何处理,此时javascript请求URL并传参数存在中文时,对URL的中文参数进行编码是按照浏览器机制进行编码的。此时编码存在乱码问题。
假设输入框中输入的内容为“测试”二字,后台Action接受到的参数值为乱码。javascript中利用encodeURI()方法进行编码。
1、利用encodeURI()在javascript中对中文URL参数进行编码时,“测试”二字会被转换为“%E6%B5%8B%E8%AF%95”
2、但是浏览器机制会认为“%”是一个转义字符,浏览器会把地址栏URL中的传递的已转换参数“%”与“%”之间的已转义字符进行处理传递到后台Action中。这样会造成与实际经过encodeURI()编码后的URL不符,因为浏览器误认为“%”是转义字符字符了,它并未将“%”认为是个普通字符。
3、要使得通过encodeURI()转换后的URL被浏览器正常处理,必须在外层再用encodeURI()处理一次已被encodeURI()编码后的RUL。这此处理encodeURI()会将已编码后的URL中被浏览器解析为转义字符的“%”再次进行编码,转换为普通字符。
4、正常处理后,前面javascript代码中②处代码为:
window.location = encodeURI(encodeURI("sayHello?user.name=" + name));
5、处理后的URL不在是通过一次 encodeURI()转换后的字符串”%E6%B5%8B%E8%AF%95“,而是经过上一步两层encodeURI()处理URL处理后的字符串”%25E6%B255%258B%25E8%AF%2595“,通过再次编码原有被浏览起解析为转义字符的”%“被再次编码,转换成了普通字符转”%25“。
此时前端javascript代码对带有中文的URL编码已经完成,并通过URL传递参数的方式传递到后台Action等待处理,Action获取到正常转换切无乱码的参数为”%25E6%B255%258B%25E8%AF%2595“,此字符串对应的中文正是我们输入的”测试“二字。
Action获取到这样的字符串无法进行处理,因为它并不是我们前端输入的源数据”测试“二字,而是进过两次encodeURI()编码后的字符串。于是我们需要利用后台的一个API对前端编码后的参数字符串进行解码,对应解码API是URLDecoder.decode(user.getName(),"UTF-8")。
URLDecoder的decode(String str,String ecn)方法有两个参数,第一个参数为待解码的字符串,第二个参数为解码时的对应编码。我么在后台使用此API进行解码的代码为:
URLDecoder.decode(user.getName(),"UTF-8");
解决方案
encodeURI(encodeURI("资源地址" ));