SpringBoot+fileUpload獲取文件上傳進度
我本人在網上找了很多關于文件上傳進度獲取的文章,普遍基于spring MVC 框架通過 fileUpload 實現(xiàn),對于spring Boot 通過 fileUpload 實現(xiàn)的帖子非常少,由于小弟學藝不精,雖然 Spring Boot 和 Spring MVC 相差不大,只是配置方式的差別,還是搞了很久,上傳此文章的目的是希望自己作為文本保留,以便日后查看備忘,并且希望通過我的例子可以幫助到其他人而已,如果各位大佬發(fā)現(xiàn)小弟對于某些知識有誤解,還請不吝賜教,先謝謝各位前輩了!
寫此篇文章之前我查了很多關于spring MVC 框架通過 fileUpload 實現(xiàn)進度條的帖子和文章,在此對各位作者表示感謝!
本功能基于commons fileUpload 組件實現(xiàn)
1.首先,不能在程序中直接使用 fileUpload.parseRequest(request)的方式來獲取 request 請求中的 multipartFile 文件對象,原因是因為在 spring 默認的文件上傳處理器 multipartResolver 指向的類CommonsMultipartResolver 中就是通過 commons fileUpload 組件實現(xiàn)的文件獲取,因此,在代碼中再次使用該方法,是獲取不到文件對象的,因為此時的 request 對象是不包含文件的,它已經被CommonsMultipartResolver 類解析處理并轉型。
CommonsMultipartResolver 類中相關源碼片段:
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException { String encoding = determineEncoding(request); FileUpload fileUpload = prepareFileUpload(encoding); try { List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request); return parseFileItems(fileItems, encoding); } catch (FileUploadBase.SizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex); } catch (FileUploadBase.FileSizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex); } catch (FileUploadException ex) { throw new MultipartException("Failed to parse multipart servlet request", ex); } }
2.由于spring 中的 CommonsMultipartResolver 類中并沒有加入 processListener 文件上傳進度監(jiān)聽器,所以,直接使用 CommonsMultipartResolver 類是無法監(jiān)聽文件上傳進度的,如果我們需要獲取文件上傳進度,就需要繼承 CommonsMultipartResolver 類并重寫 parseRequest 方法,在此之前,我們需要創(chuàng)建一個實現(xiàn)了 processListener 接口的實現(xiàn)類用于監(jiān)聽文件上傳進度。
processListener接口實現(xiàn)類:
import javax.servlet.http.HttpSession; import org.apache.commons.fileupload.ProgressListener; import org.springframework.stereotype.Component; @Component public class UploadProgressListener implements ProgressListener{ private HttpSession session; public void setSession(HttpSession session){ this.session=session; ProgressEntity status = new ProgressEntity(); session.setAttribute("status", status); } /* * pBytesRead 到目前為止讀取文件的比特數(shù) pContentLength 文件總大小 pItems 目前正在讀取第幾個文件 */ @Override public void update(long pBytesRead, long pContentLength, int pItems) { ProgressEntity status = (ProgressEntity) session.getAttribute("status"); status.setpBytesRead(pBytesRead); status.setpContentLength(pContentLength); status.setpItems(pItems); } }
ProgressEntity 實體類:
import org.springframework.stereotype.Component; @Component public class ProgressEntity { private long pBytesRead = 0L; //到目前為止讀取文件的比特數(shù) private long pContentLength = 0L; //文件總大小 private int pItems; //目前正在讀取第幾個文件 public long getpBytesRead() { return pBytesRead; } public void setpBytesRead(long pBytesRead) { this.pBytesRead = pBytesRead; } public long getpContentLength() { return pContentLength; } public void setpContentLength(long pContentLength) { this.pContentLength = pContentLength; } public int getpItems() { return pItems; } public void setpItems(int pItems) { this.pItems = pItems; } @Override public String toString() { float tmp = (float)pBytesRead; float result = tmp/pContentLength*100; return "ProgressEntity [pBytesRead=" + pBytesRead + ", pContentLength=" + pContentLength + ", percentage=" + result + "% , pItems=" + pItems + "]"; } }
最后,是繼承 CommonsMultipartResolver 類的自定義文件上傳處理類:
import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUpload; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.commons.CommonsMultipartResolver; public class CustomMultipartResolver extends CommonsMultipartResolver{ @Autowired private UploadProgressListener uploadProgressListener; @Override protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException { String encoding = determineEncoding(request); FileUpload fileUpload = prepareFileUpload(encoding); uploadProgressListener.setSession(request.getSession());//問文件上傳進度監(jiān)聽器設置session用于存儲上傳進度 fileUpload.setProgressListener(uploadProgressListener);//將文件上傳進度監(jiān)聽器加入到 fileUpload 中 try { List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request); return parseFileItems(fileItems, encoding); } catch (FileUploadBase.SizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex); } catch (FileUploadBase.FileSizeLimitExceededException ex) { throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex); } catch (FileUploadException ex) { throw new MultipartException("Failed to parse multipart servlet request", ex); } } }
3.此時,所有需要的類已經準備好,接下來我們需要將 spring 默認的文件上傳處理類取消自動配置,并將 multipartResolver 指向我們剛剛創(chuàng)建好的繼承 CommonsMultipartResolver 類的自定義文件上傳處理類。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.multipart.MultipartResolver; import com.example.listener.CustomMultipartResolver; /* * 將 spring 默認的文件上傳處理類取消自動配置,這一步很重要,沒有這一步,當multipartResolver重新指向了我們定義好 * 的新的文件上傳處理類后,前臺傳回的 file 文件在后臺獲取會是空,加上這句話就好了,推測不加這句話,spring 依然 * 會先走默認的文件處理流程并修改request對象,再執(zhí)行我們定義的文件處理類。(這只是個人推測) * exclude表示自動配置時不包括Multipart配置 */ @EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class}) @Configuration @ComponentScan(basePackages = {"com.example"}) @ServletComponentScan(basePackages = {"com.example"}) public class UploadProgressApplication { /* * 將 multipartResolver 指向我們剛剛創(chuàng)建好的繼承 CommonsMultipartResolver 類的自定義文件上傳處理類 */ @Bean(name = "multipartResolver") public MultipartResolver multipartResolver() { CustomMultipartResolver customMultipartResolver = new CustomMultipartResolver(); return customMultipartResolver; } public static void main(String[] args) { SpringApplication.run(UploadProgressApplication.class, args); } }
至此,準備工作完成,我們再創(chuàng)建一個測試用的 controller 和 html 頁面用于文件上傳。
controller:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; @Controller @RequestMapping("/uploadProgress") public class UploadController { @RequestMapping(value = "/showUpload", method = RequestMethod.GET) public ModelAndView showUpload() { return new ModelAndView("/UploadProgressDemo"); } @RequestMapping("/upload") @ResponseBody public void uploadFile(MultipartFile file) { System.out.println(file.getOriginalFilename()); } }
HTML:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"></meta> <title>測試</title>這里寫代碼片 </head> <body> 這是文件上傳頁面 <form action="/uploadProgress/upload" method="POST" enctype="multipart/form-data"> <input type="file" name="file"/> <br/> <input type="submit" value="提交"/> </form> </body> </html>
經本人測試,確實可以獲取文件上傳進度,前臺頁面修改進度條進度可以采用前臺頁面輪詢的方式訪問后臺,在相應action中通過存儲在session中的對象 status 來獲取最新的上傳進度并返回展示即可。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
如何在SpringBoot中使用logback優(yōu)化異常堆棧的輸出詳解
最近項目中整合了logback,所以下面這篇文章主要給大家介紹了關于如何在SpringBoot中使用logback優(yōu)化異常堆棧的輸出,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-05-05基于Java實現(xiàn)簡單的時序數(shù)據(jù)壓縮算法
這篇文章主要為大家詳細介紹了如何利用Java語言實現(xiàn)簡單易懂的時序數(shù)據(jù)壓縮算法,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-06-06Java PDF 添加數(shù)字簽名的實現(xiàn)方法
這篇文章主要介紹了Java PDF 添加數(shù)字簽名的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12