日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

commons-fileupload文件上傳的時候寫入圖片無數據

作者:夢凝哲雪 更新時間: 2022-02-25 編程語言

參考官網

官網

官方API

日常生活中經常會使用文件上傳下載,比如:個人頭像上傳 、半夜發美食朋友圈

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屬性共有三個值,如下

  1. application/x-www-form-urlencoded,默認值,該屬性值主要用于處理少量文本數據的傳遞,處理二進制數據、非ASCII編碼文本時,效率低;

  2. multipart/form-data,上傳二進制數據,只有使用了multipart/form-data屬性值才能完整地傳遞文件數據;

  3. 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

欄目分類
最近更新