Java實(shí)例講解文件上傳與跨域問題
Java文件上傳實(shí)例并解決跨域問題
目在Web應(yīng)用系統(tǒng)開發(fā)中,文件上傳和下載功能是非常常用的功能,今天來講一下JavaWeb中的文件上傳功能的實(shí)現(xiàn)。
了解MultipartFile接口
我們實(shí)現(xiàn)文件的上傳用到了Spring-web框架中的 MultipartFile接口,MultipartFile接口的源碼注釋中說“MultipartFile接口是 在大部分請求中接收的上載文件的表示形式?!?/p>
A representation of an uploaded file received in a multipart request.
The file contents are either stored in memory or temporarily on disk. In either case, the user is responsible for copying file contents to a session-level or persistent store as and if desired. The temporary storage will be cleared at the end of request processing.
常用方法如下表
| Method Summary | ||
|---|---|---|
byte[] |
獲取文件的字節(jié)數(shù)組 | getBytes()Return the contents of the file as an array of bytes. |
String |
獲取文件的類型 | getContentType()Return the content type of the file. |
InputStream |
獲取文件的輸入流 | getInputStream()Return an InputStream to read the contents of the file from. |
String |
獲取文件名 | getName()Return the name of the parameter in the multipart form. |
String |
獲取原始文件名(防止篡改文件類型) | getOriginalFilename()Return the original filename in the client's filesystem. |
long |
獲取文件的大小,以字節(jié)的形式) | getSize()Return the size of the file in bytes. |
boolean |
判斷文件是否為空 | isEmpty()Return whether the uploaded file is empty, that is, either no file has been chosen in the multipart form or the chosen file has no content. |
void |
將接收到的文件傳輸?shù)浇o定的目標(biāo)文件。 | transferTo(File dest)Transfer the received file to the given destination file. |
文件上傳業(yè)務(wù)代碼
Controller類
/**
* @Author: 小小張自由
* @Date: 2021/7/6 - 20:56
* @Description: 文件上傳
* @version: 1.0
*/
@Controller
@RequestMapping("upload")
public class UploadController {
@Autowired
private UploadService uploadService;
@PostMapping("image")
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file){
String url= this.uploadService.uploadImage(file);
if (StringUtils.isBlank(url)){
return ResponseEntity.badRequest().build();
}
return ResponseEntity.status(HttpStatus.CREATED).body(url);
}
}
Service類
寫了具體的業(yè)務(wù)邏輯
/**
* @Author: 小小張自由
* @Date: 2021/7/6 - 21:01
* @Description: 文件上傳
* @version: 1.0
*/
@Service
public class UploadService {
//用于判斷文件的類型,暫時(shí)只判斷了“image/gif","image/jpeg”
private static final List<String> CONTENT_TYPES= Arrays.asList("image/gif","image/jpeg");
private static final Logger LOGGER= LoggerFactory.getLogger(UploadService.class);
/**
* 業(yè)務(wù)邏輯代碼
* @param file 文件的存儲的url
* @return
*/
public String uploadImage(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
//校驗(yàn)文件類型
//方法一:截取字符串
String afterLast = StringUtils.substringAfterLast(".", originalFilename);
//方法二:使用getContentType方法
String contentType = file.getContentType();
if (!CONTENT_TYPES.contains(contentType)){
LOGGER.info("文件類型不合法:"+originalFilename);
return null;
}
//校驗(yàn)文件內(nèi)容
try {
//獲取文件流
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
if (bufferedImage==null){
LOGGER.info("文件內(nèi)容不合法:{}",originalFilename);
return null;
}
//保存到服務(wù)器 E:\Leyou\image
//將接收到的文件傳輸?shù)浇o定的目標(biāo)文件。
file.transferTo(new File("E:\\Leyou\\Image\\"+originalFilename));
//返回URL,進(jìn)行回顯
//可以使用Nginx-圖片服務(wù)器
return "http://image.leyou.com/"+originalFilename;
} catch (Exception e) {
LOGGER.info("服務(wù)器內(nèi)部錯(cuò)誤:"+originalFilename);
e.printStackTrace();
}
return null;
}
}
修改nginx配置
將文件存儲到文件服務(wù)器中
修改Nginx的配置文件nginx.conf,監(jiān)聽80端口,設(shè)置root的值為:E盤
- 圖片不能保存在服務(wù)器內(nèi)部,這樣會對服務(wù)器產(chǎn)生額外的加載負(fù)擔(dān)
一般靜態(tài)資源都應(yīng)該使用獨(dú)立域名,這樣訪問靜態(tài)資源時(shí)不會攜帶一些不必要的cookie,減小請求的數(shù)據(jù)量
server {
listen 80;
server_name image.leyou.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
root E:\\Leyou\\image;
}
}
如何繞過網(wǎng)關(guān)
每次上傳文件都會經(jīng)過網(wǎng)關(guān),必然會給網(wǎng)關(guān)帶來很大的壓力,那我們?nèi)绾卫@過網(wǎng)關(guān)呢?
1.在網(wǎng)關(guān)中配置白名單
在網(wǎng)關(guān)中配置白名單,這樣也會走網(wǎng)關(guān),只是壓力少了一點(diǎn)點(diǎn)
@Slf4j
public class AuthorizeFilter implements GlobalFilter, Ordered {
//白名單:存放放行的URL
private List<String> allowPaths;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//獲取請求的url路徑
String path = request.getURI().getPath();
boolean flag=isAllowPath(path);
if (flag) {
log.info("請求在白名單中,leyou.filter: {}",path);
//放行
return chain.filter(exchange);
} else {
//寫其他的業(yè)務(wù)邏輯
~~~~
}
}
private boolean isAllowPath(String path) {
//判斷是否允許放行
if (allowPaths.contains(path)){
return true;
}
return false;
}
2.在nginx做轉(zhuǎn)發(fā)
在nginx做轉(zhuǎn)發(fā),當(dāng)請求文件上傳時(shí),直接轉(zhuǎn)到相應(yīng)的服務(wù)
本實(shí)例使用了方法二,需要增加配置
server {
listen 80;
server_name api.leyou.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 新增加的配置,用于文件上傳
location /api/upload {
proxy_pass http://127.0.0.1:8082;
proxy_connect_timeout 600;
proxy_read_timeout 600;
rewrite "^/api/(.*)$" /$1 break;
}
# 網(wǎng)關(guān)的配置
location / {
proxy_pass http://127.0.0.1:10010;
proxy_connect_timeout 600;
proxy_read_timeout 600;
}
}
當(dāng)這樣配置之后,文件上傳就不會過網(wǎng)關(guān),減少了網(wǎng)關(guān)的壓力。但是有引來了一個(gè)新問題那就是跨域。
解決上傳文件出現(xiàn)跨域問題
由于Nginx將文件上傳的請求直接轉(zhuǎn)發(fā)到了具體服務(wù)中,不再走gateway,所以gateway中的跨域配置,不再生效了。 需要在文件上傳這個(gè)服務(wù)中單獨(dú)配置跨域。
寫配置類CorsFilter
/**
* @Author: 小小張自由
* @Date: 2021/6/15 - 11:12
* @Description: 解決 跨域問題
* @version: 1.0
*/
@Configuration
public class LeyouCorsConfiguration {
@Bean
public CorsFilter corsFilter(){
//初始化配置對象
CorsConfiguration configuration = new CorsConfiguration();
//允許跨域訪問的域名
configuration.addAllowedOrigin("*");
// configuration.setAllowCredentials(true); //運(yùn)行攜帶cookie
configuration.addAllowedMethod("*"); //代表所有請求方法
configuration.addAllowedHeader("*"); //允許攜帶任何頭信息
//初始化cors配置源對象
UrlBasedCorsConfigurationSource configurationSource=new UrlBasedCorsConfigurationSource();
configurationSource.registerCorsConfiguration("/**",configuration);
//返回CorSfilter實(shí)例,參數(shù)
return new CorsFilter(configurationSource);
}
}
到此應(yīng)該就可以上傳了,但是還是報(bào)跨域,我已經(jīng)配置好了啊,為什么還是報(bào)跨域呢?
在nginx配置中配置請求實(shí)體大小
我就想是不是Nginx的問題,然后我就一行一行的讀配置,最后發(fā)現(xiàn)
nginx配置中沒有配置請求實(shí)體大小

加上這行配置就好了
client_max_body_size 1024m;
到此這篇關(guān)于Java實(shí)例講解文件上傳與跨域問題的文章就介紹到這了,更多相關(guān)Java文件上傳跨域內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java objectUtils 使用可能會出現(xiàn)的問題
這篇文章主要介紹了java objectUtils 使用可能會出現(xiàn)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
IDEA在Maven項(xiàng)目中使用本地jar包的方法
我們在拿到舊項(xiàng)目的時(shí)候,經(jīng)常會遇到一種情況,就是這個(gè)項(xiàng)目的maven中依賴了一個(gè)本地的jar包,這種情況就需要引入這個(gè)jar包,所以本文給大家介紹了IDEA在Maven項(xiàng)目中使用本地jar包的方法,需要的朋友可以參考下2024-04-04
SpringCloud全局過慮器GlobalFilter的用法小結(jié)
這篇文章主要介紹了SpringCloud全局過慮器GlobalFilter的使用,全局過慮器使用非常廣泛,比如驗(yàn)證是否登錄,全局性的處理,黑名單或白名單的校驗(yàn)等,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07
Springboot使用filter對response內(nèi)容進(jìn)行加密方式
這篇文章主要介紹了Springboot使用filter對response內(nèi)容進(jìn)行加密方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
mybatisplus的坑?insert標(biāo)簽insert?into?select無參數(shù)問題的解決
這篇文章主要介紹了mybatisplus的坑?insert標(biāo)簽insert?into?select無參數(shù)問題的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Http Cookie機(jī)制及Cookie的實(shí)現(xiàn)原理
Cookie是進(jìn)行網(wǎng)站用戶身份,實(shí)現(xiàn)服務(wù)端Session會話持久化的一種非常好方式。Cookie最早由Netscape公司開發(fā),現(xiàn)在由 IETF 的RFC 6265標(biāo)準(zhǔn)備對其規(guī)范,已被所有主流瀏覽器所支持2021-06-06
Java靜態(tài)方法不能調(diào)用非靜態(tài)成員的原因分析
在Java中,靜態(tài)方法是屬于類的方法,而不是屬于對象的方法,它可以通過類名直接調(diào)用,無需創(chuàng)建對象實(shí)例,非靜態(tài)成員指的是類的實(shí)例變量和實(shí)例方法,它們需要通過對象實(shí)例才能訪問和調(diào)用,本文小編將和大家一起探討Java靜態(tài)方法為什么不能調(diào)用非靜態(tài)成員2023-10-10

