springboot打成jar后獲取classpath下文件失敗的解決方案
springboot打成jar后獲取classpath下文件
代碼如下:
ClassPathResource resource = new ClassPathResource("app.keystore");
File file = resource.getFile();
FileUtils.readLines(file).forEach(System.out::println);
解決方式如下:
1. Spring framework
String data = "";
ClassPathResource cpr = new ClassPathResource("static/file.txt");
try {
byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
data = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
LOG.warn("IOException", e);
}
2.use a file
ClassPathResource classPathResource = new ClassPathResource("static/something.txt");
InputStream inputStream = classPathResource.getInputStream();
File somethingFile = File.createTempFile("test", ".txt");
try {
FileUtils.copyInputStreamToFile(inputStream, somethingFile);
} finally {
IOUtils.closeQuietly(inputStream);
}
Resource resource = new ClassPathResource("data.sql");
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
reader.lines().forEach(System.out::println);
String content = new ClassPathResourceReader("data.sql").getContent();
@Value("${resourceLoader.file.location}")
@Setter
private String location;
private final ResourceLoader resourceLoader;
public void readallfilesfromresources() {
Resource[] resources;
try {
resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:" + location + "/*.json");
for (int i = 0; i < resources.length; i++) {
try {
InputStream is = resources[i].getInputStream();
byte[] encoded = IOUtils.toByteArray(is);
String content = new String(encoded, Charset.forName("UTF-8"));
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
springboot-項(xiàng)目獲取resources下文件碰到的問(wèn)題(classPath下找不到文件和文件名亂碼)
項(xiàng)目是spring-boot + spring-cloud 并使用maven 管理依賴。在springboot+maven項(xiàng)目下怎么讀取resources下的文件實(shí)現(xiàn)文件下載?
怎么獲取resources目錄下的文件?(相對(duì)路徑)
方法一:
File sourceFile = ResourceUtils.getFile("classpath:templateFile/test.xlsx"); //這種方法在linux下無(wú)法工作
方法二:
Resource resource = new ClassPathResource("templateFile/test.xlsx"); File sourceFile = resource.getFile();
我使用的是第二種。
@PostMapping("/downloadTemplateFile")
public JSONData downloadTemplateFile(HttpServletResponse response) {
String filePath = "templateFile/test.xlsx";
Resource resource = new ClassPathResource(filePath);//用來(lái)讀取resources下的文件
InputStream is = null;
BufferedInputStream bis = null;
OutputStream os = null;
try {
File file = resource.getFile();
if (!file.exists()) {
return new JSONData(false,"模板文件不存在");
}
is = new FileInputStream(file);
os = response.getOutputStream();
bis = new BufferedInputStream(is);
//設(shè)置響應(yīng)頭信息
response.setCharacterEncoding("UTF-8");
this.response.setContentType("application/octet-stream; charset=UTF-8");
StringBuffer contentDisposition = new StringBuffer("attachment; filename=\"");
String fileName = new String(file.getName().getBytes(), "utf-8");
contentDisposition.append(fileName).append("\"");
this.response.setHeader("Content-disposition", contentDisposition.toString());
//邊讀邊寫
byte[] buffer = new byte[500];
int i;
while ((i = bis.read(buffer)) != -1) {
os.write(buffer, 0, i);
}
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
return new JSONData(false,"模板文件不存在");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(os != null) os.close();
if(bis != null) bis.close();
if(is != null) is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return new JSONData("模板文件下載成功");
}
高高興興的啟動(dòng)項(xiàng)目后發(fā)現(xiàn)還是找不到文件,錯(cuò)誤日志:
java.io.FileNotFoundException: class path resource [templateFile/test.xlsx] cannot be resolved to URL because it does not exist
at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:195)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:129)
at com.citycloud.parking.support.controller.operate.OperateBusinessUserController.downloadTemplateFile(OperateBusinessUserController.java:215)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
因?yàn)槲抑繰esource resource = new ClassPathResource("templateFile/test.xlsx");就是到classPath*(注意這里有個(gè)*)下去找,然后就去項(xiàng)目本地的目錄下找classPath下是否有這個(gè)文件(maven的classPath在 “target\classes”目錄下),就發(fā)現(xiàn)并沒(méi)有這個(gè)文件在。
后面仔細(xì)想想這是Maven項(xiàng)目啊,所以就找pom.xml文件去看看,突然想起:springboot的maven默認(rèn)只會(huì)加載classPath同級(jí)目錄下文件(配置那些),其他的需要配置<resources>標(biāo)簽:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--是否替換資源中的屬性-->
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.yml</include>
<include>**/Dockerfile</include>
<include>**/*.xlsx</include>
</includes>
<!--是否替換資源中的屬性-->
<filtering>false</filtering>
</resource>
</resources>
</build>
重新啟動(dòng),再到classPath下看,發(fā)現(xiàn)有了這個(gè)文件了,同時(shí)也能獲取了。如果文件名為中文的話就會(huì)出現(xiàn)亂碼的情況。
怎么解決文件名中文亂碼?
Access-Control-Allow-Origin →* Access-Control-Allow-Credentials →true Access-Control-Allow-Headers →accessToken,Access-Control-Allow-Origin,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers Access-Control-Allow-Methods →POST,GET,PUT,PATCH,DELETE,OPTIONS,HEAD Access-Control-Max-Age →360 Content-disposition →attachment; filename="????????-??????????.xlsx" Content-Type →application/octet-stream;charset=UTF-8 Transfer-Encoding →chunked Date →Fri, 19 Apr 2019 06:47:34 GMT
上面是使用postman測(cè)試中文亂碼response響應(yīng)頭相關(guān)信息。
后面怎么改都亂碼,然后我就試著到瀏覽器中請(qǐng)求試試,結(jié)果發(fā)現(xiàn)只是postman的原因,只要文件名編碼跟返回內(nèi)容編碼一致("Content-disposition"和“ContentType”)就行:
this.response.setContentType("application/octet-stream; charset=iso-8859-1");
StringBuffer contentDisposition = new StringBuffer("attachment; filename=\"");
String fileName = file.getName();
contentDisposition.append(fileName).append("\"");
//設(shè)置文件名編碼
String contentDispositionStr = new String(contentDisposition.toString().getBytes(), "iso-8859-1");
this.response.setHeader("Content-disposition", contentDispositionStr);
到此全部結(jié)束!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java基礎(chǔ)詳解之?dāng)?shù)據(jù)類型知識(shí)點(diǎn)總結(jié)
這篇文章主要介紹了java基礎(chǔ)詳解之?dāng)?shù)據(jù)類型知識(shí)點(diǎn)總結(jié),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很大的幫助,需要的朋友可以參考下2021-04-04
Java編程利用socket多線程訪問(wèn)服務(wù)器文件代碼示例
這篇文章主要介紹了Java編程利用socket多線程訪問(wèn)服務(wù)器文件代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
淺談PrintStream和PrintWriter的區(qū)別和聯(lián)系
這篇文章主要介紹了淺談PrintStream和PrintWriter的區(qū)別和聯(lián)系,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
Java 守護(hù)線程_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
Java語(yǔ)言機(jī)制是構(gòu)建在JVM的基礎(chǔ)之上的,意思是Java平臺(tái)把操作系統(tǒng)的底層給屏蔽起來(lái),所以它可以在它自己的虛擬的平臺(tái)里面構(gòu)造出對(duì)自己有利的機(jī)制,而語(yǔ)言或者說(shuō)平臺(tái)的設(shè)計(jì)者多多少少是收到Unix思想的影響,而守護(hù)線程機(jī)制又是對(duì)JVM這樣的平臺(tái)湊合,于是守護(hù)線程應(yīng)運(yùn)而生2017-05-05
java并發(fā)編程中ReentrantLock可重入讀寫鎖
這篇文章主要介紹了java并發(fā)編程中ReentrantLock可重入讀寫鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
IDEA啟動(dòng)報(bào)錯(cuò)Internal?error.?Please?refer?to?https://jb.gg/i
這篇文章主要介紹了IDEA啟動(dòng)報(bào)錯(cuò)Internal?error.?Please?refer?to?https://jb.gg/ide/critical-startup-errors解決辦法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
使用迭代器Iterator遍歷Collection問(wèn)題
這篇文章主要介紹了使用迭代器Iterator遍歷Collection問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Java異步判斷線程池所有任務(wù)是否執(zhí)行完成的操作方法
這篇文章主要介紹了Java異步判斷線程池所有任務(wù)是否執(zhí)行完成的方法,在這個(gè)示例中,我使用了傳統(tǒng)的匿名內(nèi)部類來(lái)創(chuàng)建Callable任務(wù)(同時(shí)也提供了Lambda表達(dá)式的注釋),以便與各種Java版本兼容,需要的朋友可以參考下2024-07-07

