亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

使用AJAX實現文件拖拽上傳功能詳解

2024-04-27 15:19:18
字體:
來源:轉載
供稿:網友

關注微信公眾號“編碼很酷”

概述

對于微云、百度云等網盤提供的文件存儲服務而言,文件上傳是一個重要功能。文件上傳的方式主要有兩種:二進制數據上傳、表單上傳。本文會詳細解析表單上傳的協議規范,前端上傳文件的兩種方式:對話框選擇方式、拖拽選擇方式,服務端接收上傳的文件以及文件上傳功能的技巧等。

表單上傳協議詳解

RFC1867(https://www.ietf.org/rfc/rfc1867.txt) 規范了表單上傳的協議格式。下面給出一個例子,用Fiddler抓包工具,抓取同時上傳兩個字符串內容和一個文本文件的HTTP請求,獲取的請求內容如下:

POST http://localhost:8080/Server/uploadfile HTTP/1.1Host: localhost:8080Connection: keep-aliveContent-Length: 391Cache-Control: no-cacheOrigin: Chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcmUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryuA8AsEvrgV5BUqe5Accept: */*Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.8------WebKitFormBoundaryuA8AsEvrgV5BUqe5Content-Disposition: form-data; name="file1"value1------WebKitFormBoundaryuA8AsEvrgV5BUqe5Content-Disposition: form-data; name="file2"; filename="test2.txt"Content-Type: text/plainhello world------WebKitFormBoundaryuA8AsEvrgV5BUqe5Content-Disposition: form-data; name="file3"value3------WebKitFormBoundaryuA8AsEvrgV5BUqe5--

根據HTTP協議規范,每個請求頭后面都需要追加回車和換行符(/r/n)。消息頭和消息體之間也需要插入回車和換行符,忽略其它的請求頭部,表單上傳的格式可簡化成如下代碼,方便描述。

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryuA8AsEvrgV5BUqe5回車換行回車換行------WebKitFormBoundaryuA8AsEvrgV5BUqe5回車換行Content-Disposition: form-data; name="file2"; filename="test2.txt"回車換行Content-Type: text/plain回車換行回車換行hello world回車換行------WebKitFormBoundaryuA8AsEvrgV5BUqe5回車換行Content-Disposition: form-data; name="file3"回車換行回車換行value3回車換行------WebKitFormBoundaryuA8AsEvrgV5BUqe5--回車換行

1.添加表單描述頭部

使用表單上傳功能,需要在頭部添加如下代碼,其中“multipart/form-data”表示請求上傳的內容類型為表單,“boundary”表示分隔符,用于分割表單里面的每項內容。

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryuA8AsEvrgV5BUqe5回車換行

2.添加表單內容

表單中每項內容的類型無外乎就兩種,一種是文本類型,另外一種是文件類型。每項內容之間需要用“–+boundary+回車換行”進行分割,緊接著分隔符的代碼用于描述內容配置。其中文本類型的內容需要添加如下格式的代碼:

------WebKitFormBoundaryuA8AsEvrgV5BUqe5回車換行Content-Disposition: form-data; name="file3"回車換行回車換行value3回車換行

“name”用于描述表單的字段名稱,兩個回車換行之后就是這個字段的值。文件類型的內容跟文本類型對比多了兩個字段,“filename”用于描述上傳的文件的名稱,“Content-Type”用于描述上傳的文件類型(文件的MIME),文件類型的內容需要添加如下格式的代碼:

------WebKitFormBoundaryuA8AsEvrgV5BUqe5回車換行Content-Disposition: form-data; name="file2"; filename="test2.txt"回車換行Content-Type: text/plain回車換行回車換行hello world回車換行

添加完表單的每項內容之后,需要在后面追加“–+boundary+–+回車換行”,完成表單內容的拼接。

前端選擇文件上傳的兩種方式

1.對話框選擇方式上傳

實現對話框選擇文件,會用到如下代碼:

<form action="http://localhost:8080/Server/uploadfile" method="post" enctype="multipart/form-data"> <br> 文件: <input type="file" name="image"> <br> <input type="submit" value="上傳"> </form>

其中action字段為文件上傳的接口地址,enctype需要定義為“multipart/form-data”、input標簽的type屬性的值為“file”,對應的name為表單的字段名稱。

2.拖拽選擇方式上傳

要實現這個功能,可借助Html5新增的“Drag and drop”功能。W3C官方文檔為:https://www.w3.org/TR/2014/CR-html5-20140731/editing.html。 利用它,我們可以知道文件何時被拖動到目標區域、文件何時離開目標區域、有哪些文件被拖到了目標區域。接下來就具體聊聊“Drag and drop”功能。

如何知道文件何時拖動到目標區域又何時離開目標區域?

HTML中的每個標簽都能夠設置跟拖動相關的事件,拖動事件的回調函數解釋如下:

事件 描述
ondragstart 拖動操作開始時調用(部分瀏覽器不回調此方法)
ondrag 拖動過程中調用(部分瀏覽器不回調此方法)
ondragenter 剛拖動到目標元素區域時調用
ondragover 在目標元素區域內拖動時調用,此方法會隔一段時間調用一次
ondragleave 拖動離開目標元素區域時調用
ondragend 拖動結束時回調(部分瀏覽器不回調此方法)
ondrop 在目標元素區域內放開拖動內容時調用

注冊事件可以使用如下代碼:

//element可以為HTML標簽、documentelement.ondragstart = function(ev) { console.log('ondragstart');}

注意:

瀏覽器默認在拖放完成時會打開所拖放的文件,正確的做法是要調用事件對象的PReventDefault方法用來阻止事件的默認動作的執行。

//element可以為HTML標簽、documentelement.ondragover = function(ev) { ev.preventDefault(); //do something}

如何獲取拖動的文件?

上面所列舉的回調函數,每個回調函數里面都有一個參數DragEvent,DragEvent的接口定義語言描述如下:

interface DragEvent : MouseEvent { readonly attribute DataTransfer? dataTransfer;};

可以看到拖動事件接口繼承于鼠標事件接口,其中有個屬性dataTransfer(數據傳輸者)用于傳輸拖動的內容,DataTransfer的接口定義語言如下:

interface DataTransfer { attribute DOMString dropEffect; attribute DOMString effectAllowed; readonly attribute DataTransferItemList items; void setDragImage(Element image, long x, long y); /* old interface */ readonly attribute DOMString[] types; DOMString getData(DOMString format); void setData(DOMString format, DOMString data); void clearData(optional DOMString format); readonly attribute FileList files;};

其中的setData方法用于設置要傳輸的內容,getData方法用于獲取傳輸的內容。當要實現從一個元素中拖動內容到另外一個元素區域時可以使用者兩個方法。拖動文件時值需要使用files屬性,其值被瀏覽器設置進去了,因此只要獲取即可。那么獲取files的最佳時機是什么時候,當然是在ondrop方法回調時最佳。

dz.ondrop = function(ev) { //阻止瀏覽器默認打開文件的操作 ev.preventDefault(); //表單上傳文件...}

如何上傳獲取到的文件?

使用Ajax即可通過表單方式上傳文件,附上前端拖拽上傳的完整代碼。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"><head> <title>HTML5拖拽上傳</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="description" content="" /> <meta name="keyWords" content="" /> <style type="text/CSS"> #dropzone { width: 300px; height: 300px; border: 2px dashed gray; } #dropzone.over { width: 300px; height: 300px; border: 2px dashed red; } </style></head><body> <div id="dropzone" dropEffect="link"></div></body><script type="text/javascript">function uploadFile(formData) { var xhr = new xmlhttpRequest(); xhr.open('POST', 'http://localhost:8080/Server/uploadfile', true); xhr.send(formData);}var dz = document.getElementById('dropzone');dz.ondragover = function(ev) { //阻止瀏覽器默認打開文件的操作 ev.preventDefault(); this.className = 'over';}dz.ondragleave = function() { this.className = '';}dz.ondrop = function(ev) { this.className = ''; //阻止瀏覽器默認打開文件的操作 ev.preventDefault(); //表單上傳文件 var formData = new FormData(); formData.append('file', ev.dataTransfer.files[0]); uploadFile(formData);}</script></html>

服務端處理上傳的文件

服務端代碼本人采用JAVAEE開發,文件上傳使用到commons fileupload組件:https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi,commons fileupload依賴common io庫。

完整代碼如下:

package com.servlet;import java.io.File;import java.io.IOException;import java.util.Iterator;import java.util.List;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;@WebServlet(name = "uploadfile", urlPatterns = "/uploadfile")public class UploadFileServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { ServletContext servletContext = this.getServletConfig() .getServletContext(); // Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory(); // Set factory constraints String path = "D://upload"; File uploadDir = new File(path); if (!uploadDir.exists()) { uploadDir.mkdirs(); } factory.setRepository(new File(uploadDir.getAbsolutePath())); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // Set overall request size constraint upload.setSizeMax(-1); // Parse the request List<FileItem> items = upload.parseRequest(req); // Process the uploaded items Iterator<FileItem> iter = items.iterator(); while (iter.hasNext()) { FileItem item = iter.next(); if (item.isFormField()) { // 普通表單數據 } else { // 文件表單數據 item.write(new File(uploadDir.getAbsolutePath() + File.separator + item.getName())); } } } catch (Exception e) { e.printStackTrace(); } }}

文件上傳功能的一些技巧

1.實現文件秒傳功能

微云、百度云就含有文件秒傳功能,其實現原理其實很簡單,文件可以用其md5來區分差異性。上傳文件時計算文件的MD5,只要服務器上存在相同MD5值的文件,則不會真正的上傳文件,而是把網盤上文件的索引存儲到當前用戶信息中。所以一般網盤上不會出現MD5值相同的文件。

2.防止可執行文件注入攻擊

以tomcat服務器為例,WEB-INF目錄可以被瀏覽器訪問。如果用戶將可執行的文件如xx.jsp上傳到這個目錄,里面編寫了刪除文件目錄的代碼,則當瀏覽器訪問這個xx.jsp文件時,這段惡意代碼就會被執行,這顯然是惡意攻擊。為了阻止這種行為,正確的做法是過濾掉可執行文件,不讓其上傳,這種判斷前端和后端都需要做,前端做的目的是可以減輕服務端的判斷壓力,后端做是為了阻止模擬的HTTP請求上傳惡意文件。

更多

長按下圖->識別圖中二維碼或者掃一掃關注我的公眾號。

微信公眾號


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩中文字幕精品视频| 国产中文欧美精品| 国产91精品青草社区| 欧美激情精品久久久久久大尺度| 亚洲国产精品久久久久久| 精品成人久久av| 日韩精品在线观看一区| 黄色一区二区在线观看| 久久91精品国产| 欧美孕妇与黑人孕交| 日韩av一区在线观看| 国产精自产拍久久久久久蜜| 欧美高清无遮挡| 成人做爰www免费看视频网站| 欧美一区深夜视频| 亲爱的老师9免费观看全集电视剧| 日本高清不卡在线| 中文字幕在线视频日韩| 国产亚洲欧美视频| 九九视频直播综合网| 日韩av在线天堂网| 欧美做受高潮电影o| 日韩大陆欧美高清视频区| 中文字幕亚洲欧美一区二区三区| 91精品国产色综合久久不卡98| 中文字幕日韩欧美在线| 最近更新的2019中文字幕| 欧美精品久久久久a| 欧美日韩一区二区免费视频| 亚洲高清福利视频| 97超碰国产精品女人人人爽| 国产精品成人一区二区| 久久久人成影片一区二区三区观看| 97国产精品视频| 午夜精品一区二区三区在线| 日韩精品免费综合视频在线播放| 欧美重口另类videos人妖| 成人精品久久一区二区三区| 欧美激情a∨在线视频播放| 欧美高清视频一区二区| 日韩欧美精品在线观看| 日韩一区二区三区国产| 日韩电影免费在线观看| 日韩av成人在线| 最近2019中文字幕第三页视频| 日韩亚洲欧美中文高清在线| 亚洲欧美色婷婷| 欧美日韩国产一区二区三区| 亚洲精品久久久久久久久久久久| 亚洲欧美激情另类校园| 久久精品欧美视频| 国自产精品手机在线观看视频| 日韩av免费看网站| 精品中文字幕乱| 成人久久18免费网站图片| 日本电影亚洲天堂| 久久国产精品网站| 欧美与欧洲交xxxx免费观看| 亚洲精品720p| 亚洲美女av在线| 777777777亚洲妇女| 国产伊人精品在线| 成人免费看吃奶视频网站| 亚洲欧美国产一本综合首页| 欧美富婆性猛交| 欧美高清videos高潮hd| 国产精品久久久久久五月尺| 亚洲精品电影在线| 亚洲激情第一页| 久久艳片www.17c.com| 91成人免费观看网站| 亚洲午夜激情免费视频| 欧美高清一级大片| 日韩亚洲欧美成人| 宅男66日本亚洲欧美视频| 91影院在线免费观看视频| 久久精品中文字幕一区| 久久全球大尺度高清视频| 国产精品免费视频xxxx| 国产精品成av人在线视午夜片| 成人h片在线播放免费网站| 日韩欧美第一页| 久久精品亚洲精品| 亚洲网址你懂得| 97超视频免费观看| 久久精品视频亚洲| 97人洗澡人人免费公开视频碰碰碰| 成人在线视频网站| 疯狂欧美牲乱大交777| 久久躁日日躁aaaaxxxx| 在线a欧美视频| 国产欧美一区二区| 中文字幕欧美日韩va免费视频| 亚洲欧美综合图区| 亚洲欧美在线免费| 欧美激情一区二区久久久| 亚洲精品91美女久久久久久久| 成人网欧美在线视频| 日韩av毛片网| 欧美精品免费在线| 欧美xxxx做受欧美| 久久久黄色av| 亚洲精品一区在线观看香蕉| 欧美中文字幕在线播放| 精品视频—区二区三区免费| 国产美女91呻吟求| 久久久久久97| 亚洲精品国产免费| 日韩网站免费观看高清| 亚洲欧洲国产精品| 国产精品老女人精品视频| 国产一区二区三区精品久久久| 日韩av影视在线| 欧美性猛交xxxx乱大交蜜桃| 色婷婷亚洲mv天堂mv在影片| 久99九色视频在线观看| 日韩中文字幕网站| 日韩中文字幕免费看| 欧美日韩国产在线| 日韩av在线看| 久久久久www| 欧美综合国产精品久久丁香| 国产精品综合久久久| 亚洲自拍偷拍在线| 久久综合免费视频| 精品视频久久久久久久| 欧美性极品少妇精品网站| 久久91精品国产91久久跳| 久久人人爽人人爽人人片亚洲| 亚洲美女av在线播放| 久久九九有精品国产23| 91手机视频在线观看| 国产精品99蜜臀久久不卡二区| 九九热精品视频| 日韩成人av网址| 欧美性极品少妇精品网站| 日韩在线观看网址| 欧美成人精品一区二区三区| 日韩精品视频在线播放| 永久免费毛片在线播放不卡| 久久久女人电视剧免费播放下载| 日韩一区视频在线| 成人在线精品视频| 久久久人成影片一区二区三区| 亚洲高清一区二| 日韩精品免费在线观看| 日韩大片免费观看视频播放| 欧美老女人性生活| 国产精品美女久久| 久久久久久久久久国产精品| 亚洲女性裸体视频| 成人免费看黄网站| 欧美日韩国产专区| 日韩中文字幕不卡视频| 亚洲国产精品视频在线观看| 亚洲va码欧洲m码| 日韩高清电影好看的电视剧电影| 亚洲精品电影久久久| 狠狠躁18三区二区一区| 国产成人精品一区| 96sao精品视频在线观看| 亚洲成人久久网| 亚洲天堂影视av| 日韩av大片免费看|