網站首頁 編程語言 正文
參考官網
日常生活中經常會使用文件上傳下載,比如:個人頭像上傳 、半夜發美食朋友圈
Apache Commons FileUpload 文件上傳 為我們簡化底層IO代碼的實現
1、支持多文件上傳
本案基于 H5+ Servlets 實現
一、引入相關依賴及位置圖
commons-fileupload-1.4.jar
commons-io-2.11.0.jar
資源鏈接:
https://pan.baidu.com/s/1NKuCbsKlSrjPp5lbi1QMlA
提取碼: grxy
–來自百度網盤超級會員v6的分享
二、版本要求 建議 JDK 1.8
三、制作上傳所使用的網頁
注意事項
1、上傳文件時,form表單的method屬性必須設置為post,不能是get
2、上傳文件時,需要在表單屬性中添加enctype屬性,該屬性用于設置表單提交數據的編碼方式,由于文件傳至服務器時與一般文本類型的編碼方式不同,需要設置為multipart/form-data。
PS:enctype屬性共有三個值,如下
-
application/x-www-form-urlencoded,默認值,該屬性值主要用于處理少量文本數據的傳遞,處理二進制數據、非ASCII編碼文本時,效率低;
-
multipart/form-data,上傳二進制數據,只有使用了multipart/form-data屬性值才能完整地傳遞文件數據;
-
text/plain,主要用于向服務器傳遞大量文本數據,如電子郵件、發布長篇新聞等。
網頁代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用Commons-FileUpload組件實現文件上傳</title>
</head>
<body>
<!-- ${pageContext.request.contextPath}/FileUpload JSP網頁可用 -->
<form action="FileUpload" method="post" enctype="multipart/form-data">
用戶名:<input type="text" name="userName">
<!-- 加上multiple屬性,可以一次上傳多個文件 -->
選擇文件:<input type="file" name="myFile" multiple>
<input type="submit" value="上傳">
</form>
</body>
</html>
四、后臺處理程序 此時使用的Java中的Servlet
后臺源碼
/**
* 文件上傳處理器
* company 源辰信息
* @author 38929
* @date 2021年10月25日
* @version 1.0
* Email 1198865589@qq.com
*/
@WebServlet(description = "FileUpload", urlPatterns = { "/FileUpload" })
public class FileUpload extends HttpServlet {
private String path = "../temp/image"; //默認的上傳路徑
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//編碼級設定
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
//enctype屬性是否是multipart/form-data
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
String userName=""; //上傳者
StringBuffer fileStr = new StringBuffer(); //上傳的文件名,最后輸出用
if ( !isMultipart ){ //不是文件上傳
return;
}
//獲取上傳路徑 服務器中項目的絕對路徑 C:\..\項目號名\ + ../temp/image
String savePath = request.getServletContext().getRealPath("/") + path;
//開始文件上傳
try {
FileItemFactory factory=new DiskFileItemFactory(); //工廠實例
//ServletFileUpload實例依賴于FileItemFactory工廠 解析器
ServletFileUpload upload=new ServletFileUpload(factory);
//解析表單字段,封裝成一個FileItem實例的集合
List<FileItem> itemList=upload.parseRequest(request);
Iterator<FileItem> iterator=itemList.iterator(); //迭代器
while ( iterator.hasNext() ){ // 依次處理每個表單域
FileItem fileItem = iterator.next(); //依次解析每一個FileItem實例,即表單字段
System.out.println( fileItem );
if (fileItem.isFormField( )){
//普通表單字段
if (fileItem.getFieldName().equals("userName")){
//如果表單屬性name的值的userName,就獲取這個表單字段的值
userName=fileItem.getString("UTF-8");
}
}else { //如果item是文件上傳表單域
String fileUpName = fileItem.getName(); //用戶上傳的文件名
System.out.println( fileUpName );
//防止圖片因重名造成覆蓋 TODO 待優化 如何識別是同一張圖片
String newFileUpName = UUID.randomUUID().toString().replaceAll("-", "") + "-" + fileUpName;
File uplodeFile = new File( savePath, newFileUpName);//要保存到的文件
/*
if ( !uplodeFile .exists() ){
uplodeFile .createNewFile(); //一開始肯定是沒有的,所以先創建出來
}
*/
//底層代碼會幫我們自動創建文件 不需要自己判斷 否則 會報錯
//org.apache.commons.io.FileExistsException: Destination 'D:\屏幕截圖(7).png' already exists
fileItem.write( uplodeFile ); //寫入,保存到目標文件
fileStr.append( newFileUpName + "、");
}
}
fileStr.replace(fileStr.lastIndexOf("、"), fileStr.length(), "");
PrintWriter writer = response.getWriter();
writer.print("<script>alert('用戶"+userName+"上傳了文件"+fileStr+"')</script>");
}catch (Exception e){
e.printStackTrace();
}
}
}
五、注意事項
1、異常提示: 文件已經存在
異常代碼
org.apache.commons.io.FileExistsException: File element in parameter 'null' already exists: 'C:\Users\ASUS\Desktop\down\apache-tomcat-9.0.52\webapps\jw2001-5\..\temp\image\fb1925394d814b5aaead6a52695683c8-屏幕截圖(1).png'
異常圖
分析思路
檢查發現關鍵代碼
fileItem.write( uplodeFile ); //寫入,保存到目標文件
文件輸出備用代碼
//寫入文件
InputStream is = fileItem.getInputStream();
OutputStream os = new FileOutputStream( uplodeFile );
byte[] bt = new byte[ (int) fileItem.getSize() ];
int len = 0;
while( ( len = is.read( bt ) ) != -1 ) {
os.write(bt, 0 , len);
}
os.close();
is.close();
官方解釋如下
void write(File file)
throws Exception
A convenience method to write an uploaded item to disk. The client code is not concerned with whether or not the item is stored in memory, or on disk in a temporary location. They just want to write the uploaded item to a file.
This method is not guaranteed to succeed if called more than once for the same item. This allows a particular implementation to use, for example, file renaming, where possible, rather than copying all of the underlying data, thus gaining a significant performance benefit.
Parameters:
file - The File into which the uploaded item should be stored.
Throws:
Exception - if an error occurs.
檢查源碼
/**
* A convenience method to write an uploaded item to disk. The client code
* is not concerned with whether or not the item is stored in memory, or on
* disk in a temporary location. They just want to write the uploaded item
* to a file.
* <p>
* This implementation first attempts to rename the uploaded item to the
* specified destination file, if the item was originally written to disk.
* Otherwise, the data will be copied to the specified file.
* <p>
* This method is only guaranteed to work <em>once</em>, the first time it
* is invoked for a particular item. This is because, in the event that the
* method renames a temporary file, that file will no longer be available
* to copy or rename again at a later time.
*
* @param file The <code>File</code> into which the uploaded item should
* be stored.
*
* @throws Exception if an error occurs.
*/
@Override
public void write(File file) throws Exception {
if (isInMemory()) {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(file);
fout.write(get());
fout.close();
} finally {
IOUtils.closeQuietly(fout);
}
} else {
File outputFile = getStoreLocation();
if (outputFile != null) {
// Save the length of the file
size = outputFile.length();
/*
* The uploaded file is being stored on disk
* in a temporary location so move it to the
* desired file.
*/
FileUtils.moveFile(outputFile, file);
} else {
/*
* For whatever reason we cannot write the
* file to disk.
*/
throw new FileUploadException(
"Cannot write uploaded file to disk!");
}
}
}
底層調用了FileOutputStream進行數據的輸出, 而該方法會自動創建不存在的目錄
導致文件沖突 產生異常 從而未生效
錯誤代碼
注釋掉就行
if ( !uplodeFile .exists() ){
uplodeFile .createNewFile(); //一開始肯定是沒有的,所以先創建出來
}
錯誤效果圖
正常效果圖
1、上傳操作
2、成功提示
到此完美成功!
當然還需更多優化改進!
TODO
1、上傳進度條
2、文件類型 、大小 、數量
3、文件下載
原文鏈接:https://blog.csdn.net/Klhz555/article/details/121946923
相關推薦
- 2022-11-12 C語言內存操作函數使用示例梳理講解_C 語言
- 2022-10-20 詳解Python中的?type()函數_python
- 2024-02-01 啟動jar報錯(文件名、目錄名或卷標語法不正確。)
- 2022-10-31 ?Go?語言實現?HTTP?文件上傳和下載_Golang
- 2022-05-25 詳解C++類的成員函數做友元產生的循環依賴問題_C 語言
- 2022-11-18 Oracle移動數據文件不停機和停機兩種方式詳解_oracle
- 2022-03-21 C語言楊輝三角兩種實現方法_C 語言
- 2021-12-07 Centos8搭建基于kdc加密的nfs_Linux
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支