初步學習FineUploader(java)

一、認識FineUploader的功能:

進入示例網站:https://fineuploader.com/demos.html#basic-setup;

二、準備相關的js,css 

Build Fine Uploader yourself from the GitHub repo

  1. git clone https://github.com/FineUploader/fine-uploader.git

  2. cd fine-uploader

  3. npm install

  4. make build


make build之後將生成一個“_build”目錄,其中包含CSS、JS、圖像和模板文件,以供所有可能構建的Fine Uploader

fine-uploader.PNG

上面是下載的fine-Uploader前臺所需的代碼。下面來看看後臺代碼:

三:服務器示例代碼:

git clone https://github.com/FineUploader/server-examples/blob/master/java/UploadReceiver.java

server.PNG

我們所需要的java代碼就在java那個目錄下:


s3.PNG

到現在,準備工作已經完成。


四、新建一個自己的web項目:

new.PNG

1、輸入工程名,finish之後目錄結構是這樣的:

1.PNG

2、添加剛纔在server-example中的java文件到src下:

然後這樣直接會報錯,應該在java文件中修改所在包名,並引入所有需要的jar包:

2.PNG


目前暫時引入了這些包。

3、接下來新建html了:

從剛纔在git上下載的fine-Uploader文件夾中的client/html/templates中找到這次示例要用的html文件:gallery.html

https://docs.fineuploader.com/features/styling.html  這裏會涉及這幾個文件的講解)

3.PNG

<script type="text/template" id="qq-template">
    <div class="qq-uploader-selector qq-uploader qq-gallery" qq-drop-area-text="Drop files here">
        <div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container">
            <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div>
        </div>
        <div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone>
            <span class="qq-upload-drop-area-text-selector"></span>
        </div>
        <div class="qq-upload-button-selector qq-upload-button">
            <div>Upload a file</div>
        </div>
        <span class="qq-drop-processing-selector qq-drop-processing">
            <span>Processing dropped files...</span>
            <span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span>
        </span>
        <ul class="qq-upload-list-selector qq-upload-list" role="region" aria-live="polite" aria-relevant="additions removals">
            <li>
                <span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span>
                <div class="qq-progress-bar-container-selector qq-progress-bar-container">
                    <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div>
                </div>
                <span class="qq-upload-spinner-selector qq-upload-spinner"></span>
                <div class="qq-thumbnail-wrapper">
                    <img class="qq-thumbnail-selector" qq-max-size="120" qq-server-scale>
                </div>
                <button type="button" class="qq-upload-cancel-selector qq-upload-cancel">X</button>
                <button type="button" class="qq-upload-retry-selector qq-upload-retry">
                    <span class="qq-btn qq-retry-icon" aria-label="Retry"></span>
                    Retry
                </button>

                <div class="qq-file-info">
                    <div class="qq-file-name">
                        <span class="qq-upload-file-selector qq-upload-file"></span>
                        <span class="qq-edit-filename-icon-selector qq-btn qq-edit-filename-icon" aria-label="Edit filename"></span>
                    </div>
                    <input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text">
                    <span class="qq-upload-size-selector qq-upload-size"></span>
                    <button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete">
                        <span class="qq-btn qq-delete-icon" aria-label="Delete"></span>
                    </button>
                    <button type="button" class="qq-btn qq-upload-pause-selector qq-upload-pause">
                        <span class="qq-btn qq-pause-icon" aria-label="Pause"></span>
                    </button>
                    <button type="button" class="qq-btn qq-upload-continue-selector qq-upload-continue">
                        <span class="qq-btn qq-continue-icon" aria-label="Continue"></span>
                    </button>
                </div>
            </li>
        </ul>

        <dialog class="qq-alert-dialog-selector">
            <div class="qq-dialog-message-selector"></div>
            <div class="qq-dialog-buttons">
                <button type="button" class="qq-cancel-button-selector">Close</button>
            </div>
        </dialog>

        <dialog class="qq-confirm-dialog-selector">
            <div class="qq-dialog-message-selector"></div>
            <div class="qq-dialog-buttons">
                <button type="button" class="qq-cancel-button-selector">No</button>
                <button type="button" class="qq-ok-button-selector">Yes</button>
            </div>
        </dialog>

        <dialog class="qq-prompt-dialog-selector">
            <div class="qq-dialog-message-selector"></div>
            <input type="text">
            <div class="qq-dialog-buttons">
                <button type="button" class="qq-cancel-button-selector">Cancel</button>
                <button type="button" class="qq-ok-button-selector">Ok</button>
            </div>
        </dialog>
    </div>
</script>

將上面的代碼全部複製到新建的html文件:

然後在代碼中引入fineUploader的核心js和css:

gallery.html必須使用fine-uploader-gallery.css文件,

以上是假如有圖片上傳的顯示模板,那麼得需要一個供圖片拖動到的位置:(如示例網站):
5.PNG

此時此刻,我們需要對定義的該位置,“綁定”fine-Uploader組件:

<script type="text/javascript">  
function createUploader() {  
    uploader = new qq.FineUploader({  
    		
        	element: document.getElementById('fine-uploader-gallery'),  
                autoUpload: true,  //是否自動上傳,true就會自動上傳
        	multiple : true, //multiple選項:默認爲true,用戶可以一次選擇多個文件並上傳。
            request: {  //後臺接受文件上傳的URL路徑。設置其中的endpoint屬性。
                endpoint: '/FineUploaderServerExample/servlet/UploadReceiver'
            },  
            /**
            session: {  
                endpoint: '<%=request.getContextPath()%>/XXXX/XXXX',  
                params: {'id': ${bulletin.id}}  
            },
            */
            deleteFile: {  //用於刪除已上傳的文件。可以刪除的文件必須是在同一個頁面中已經成功上傳,或者由session選項初始化的文件列表。
                enabled: true,  
                endpoint: '/FineUploaderServerExample/servlet/UploadReceiver',  //後臺用於刪除文件的URL地址。返回值和上傳時一樣必須含有“success”屬性
                method: 'POST',//必須設置爲'post'
                forceConfirm: true,  //是否出現刪除確認的對話框,默認值爲false
                confirmMessage: '確定要刪除文件 {filename} 嗎? 不可恢復!!', 
                params: {
                    foo: "bar"
                },
                deletingFailedText: '刪除失敗!'  
            }, 
            text : {
            	uploadButton : "<a href='#' class='add_files'><span class='icon-attachment'></span>瀏覽</a>"
            	},
            
            validation: 
            	      {
            	           allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'],
            	           itemLimit:12,
            	           sizeLimit: 2048 // 200 kB = 200 * 1024 bytes
            	     },
            editFilename: {  
                   enabled: false  
            }, 
            onSubmit:  function(id,  fileName)  {
            	
            },
            onUpload: function(id, fileName) {
            	
            },
            //loaded:表示已經上傳到服務器端數據的大小[byte].
            //total: 需要上傳文件的大小.
            onProgress:  function(id,  fileName,  loaded,  total)  {
            	
            },
            onComplete:  function(id,  fileName,  responseJSON)  {
            	
            },
            //id表示第幾個開始上傳的文件,Fine Uploder定義是默認從0開始計數.
           //fileName:上傳文件的文件名.
            onCancel:  function(id,  fileName)  {
            	
            },
            callbacks: {  
                onAllComplete:  function(successIDs, failIDs)  {  
                    if(submitFile)  
                        submitdata(successIDs);  
                }  
            },
            params:{
            	param1:"value1",
            	param2:"value2"
            },
            retry: {
                enableAuto: true
            },
            
            debug:true
    });  
}  
window.onload = createUploader;  
</script>
 endpoint: '/FineUploaderServerExample/servlet/UploadReceiver',

endpoint這裏:FineUploaderServerExample是工程名,/servlet/UploaderReceiver是訪處理post請求的servlet的類。

至此,test.html就基本完成了。(然後加上web.xml)

4、修改剛纔複製到項目中的server-example中的Java代碼:

通過代碼結構可以看出,UploadReceiver.java是直接處理上傳和刪除請求的類:

由於前臺endpoint中請求的後臺url都是post請求的,所以我們首先來看看doPost方法:

大致來看,第一步,根據請求的HttpRequest,臨時存放文件的文件夾,上下文傳入MultipartUploadParser這個類。

根據MultipartUploadParser類的構造方法,返回一個MultipartUploadParser實體。那我們看看在構造方法裏是執行了什麼操作:

public MultipartUploadParser(HttpServletRequest request, File repository, ServletContext context) throws Exception
	{
	//創建臨時文件夾
	    if (!repository.exists() && !repository.mkdirs())
	    {
		throw new IOException("Unable to mkdirs to " + repository.getAbsolutePath());
	    }
            //servlet實現文件上傳---核心API—DiskFileItemFactory
	    fileItemsFactory = setupFileItemFactory(repository, context);
            //在setupFileItemFactory中指定臨時文件目錄,並給該目錄設置了一個文件清理跟蹤器
            //臨時文件在不再被使用的時候(如果相應的java.io.File是可回收的則更好)會自動被刪除.(文件清理跟蹤器)
            ServletFileUpload upload = new ServletFileUpload(fileItemsFactory);
            List<FileItem> formFileItems = upload.parseRequest(request);
                //將request進行解析並添加到FileItem中
		parseFormFields(formFileItems);

		if (files.isEmpty())
		{
			log.warn("No files were found when processing the requst. Debugging info follows.");

			writeDebugInfo(request);

			throw new FileUploadException("No files were found when processing the requst.");
		}
		else
		{
			if (log.isDebugEnabled())
			{
				System.out.println("log.isDebugEnabled");
				writeDebugInfo(request);
			}
		}
	}

獲得一個 MultipartUploadParser之後,再據此獲得一個RequestParser類的實例。

static RequestParser getInstance(HttpServletRequest request, MultipartUploadParser multipartUploadParser) throws Exception
    {
        RequestParser requestParser = new RequestParser();

        if (multipartUploadParser == null)
        {
            if (request.getMethod().equals("POST") && request.getContentType() == null)
            {
                parseXdrPostParams(request, requestParser);
            }
            else
            {
                requestParser.filename = request.getParameter(FILENAME_PARAM);
                parseQueryStringParams(requestParser, request);
            }
        }
        else
        {
            requestParser.uploadItem = multipartUploadParser.getFirstFile();
            requestParser.filename = multipartUploadParser.getFirstFile().getName();

            //params could be in body or query string, depending on Fine Uploader request option properties
            parseRequestBodyParams(requestParser, multipartUploadParser);
            parseQueryStringParams(requestParser, request);
        }

        removeQqParams(requestParser.customParams);

        return requestParser;
    }

RequestParser的作用就是將前臺傳過來的文件信息獲取,並填充自己的屬性:

6.PNG

獲得RequestParser之後,用writeFileForMultipartRequest方法寫到指定位置:

private void writeFileForMultipartRequest(RequestParser requestParser) throws Exception {
		File dir = new File(UPLOAD_DIR, requestParser.getUuid());//在指定的文件夾下,創建一個子文件夾,名爲對應的uuid
		dir.mkdirs();
		System.out.println("writeFileForMultipartRequest === ");
		if (requestParser.getPartIndex() >= 0) {
			writeFile(requestParser.getUploadItem().getInputStream(),
					new File(dir, requestParser.getUuid() + "_" + String.format("%05d", requestParser.getPartIndex())),
					null);

			if (requestParser.getTotalParts() - 1 == requestParser.getPartIndex()) {
				File[] parts = getPartitionFiles(dir, requestParser.getUuid());
				File outputFile = new File(dir, requestParser.getOriginalFilename());//timg.jpg
				for (File part : parts) {
					mergeFiles(outputFile, part);
				}

				assertCombinedFileIsVaid(requestParser.getTotalFileSize(), outputFile, requestParser.getUuid());
				deletePartitionFiles(dir, requestParser.getUuid());
			}
		} else {
			writeFile(requestParser.getUploadItem().getInputStream(), new File(dir, requestParser.getFilename()), null);
		}
	//	option.add(++id, requestParser.getFilename(), requestParser.getUuid(), requestParser.getUuid().substring(5, 8));
	}

//需要注意的是,這個文件夾如果沒有指定絕對路徑,那麼遇到過的情況是:1、在桌面,2、在eclipse的安裝目錄。

我這寫的是絕對路徑。

寫入的文件會這樣存放:

8.PNG

每個文件的上層文件夾的名字就是其對應的uuid。

5、運行項目,添加缺少的文件,比如前臺需要的gif圖:

7.PNG

將報錯的這幾個文件都加入到css文件夾中。這樣還可以完成刪除操作。

9.PNG

這樣就完成了fineuploader的例子使用。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章