ตัวอย่างในบทความนี้แบ่งปันเทคโนโลยีการอัปโหลดไฟล์ Java สำหรับการอ้างอิงของคุณกับคุณ เนื้อหาเฉพาะมีดังนี้
รูปร่าง:
ไคลเอนต์ต้องใช้ประเภทข้อมูลแบบหลายส่วน/ฟอร์ม-ข้อมูลเพื่อแสดงประเภทข้อมูลคอมโพสิตเมื่อส่ง HTTP ตอนนี้:
ใช้แท็ก HTML ในรูปแบบ
ต้องใช้แพ็คเกจ:
Commons-fileupload.jar เครื่องมือการอัปโหลดหลักอยู่ในแพ็คเกจนี้
แพ็คเกจ Commons-io.jar จำเป็นต้องอัปโหลดไฟล์
คำอธิบายโดยละเอียดเกี่ยวกับการอัปโหลดคลาสไฟล์:
DiskFileItemFactory - สร้างไดเรกทอรีไฟล์การตรวจสอบเวลาซึ่งหมายถึงขนาดพื้นที่แคช
ServletFileUpload ใช้เพื่อแยกวิเคราะห์ httpservletrequest ส่งคืนชุดวัตถุไฟล์
FileItem แสดงวัตถุแต่ละไฟล์ที่อัพโหลดโดยผู้ใช้
<%@ page language = "java" import = "java.util.*" pageencoding = "utf-8"%> <! doctype html สาธารณะ "-// w3c // dtd html 4.01 transitional // en"> <html> <head> บอร์ด-เข้าใจเลเยอร์พื้นฐาน </font> <!-multipart/form-data: multipart (ไม่เพียง แต่ไฟล์ แต่ยังรวมถึงชิ้นส่วน)-> <form action = "<%= request.getContextPath ()%>/upload0" method = "post" enctype = "multipart/form-data" <!-ชื่อไฟล์ที่อัปโหลดไม่สามารถเป็นภาษาจีนได้มิฉะนั้นชื่อไฟล์ที่ได้รับจะอ่านไม่ออก แต่ตัวอย่างต่อไปนี้สามารถแก้ปัญหานี้ได้-> </form> <br/> <font color = "สีแดง" ขนาด = "6"> ใช้เครื่องมืออัปโหลดไฟล์ Apache method = "post" enctype = "multipart/form-data"> ไฟล์: <input type = "file" name = "file"/> <อินพุต type = "submit" value = "upload"/> </form> <font color = "red" size = "6"> ใช้เครื่องมืออัปโหลดไฟล์ Apache enctype = application/x-www-form-urlencoded (ค่าเริ่มต้น) </p> <p> post2 (อัพโหลดฟอร์มไฟล์): enctype = multipart/form-data: multipart (ไม่เพียง แต่ไฟล์ แต่ยังรวมถึง </p> <form = "<%= request.getContext type = "file" name = "file"/> <!-post2 (อัปโหลดไฟล์ไฟล์)-> <br/> คำอธิบายไฟล์: <อินพุต type = "text" name = "desc"/> <!-post1 (รูปแบบปกติ)-> <br/> ไฟล์ 2: <อินพุต type = "ไฟล์" 2: <อินพุต type = "file" name = "file"/> <br/> คำอธิบายไฟล์ 2: <อินพุตประเภท = "text" name = "desc"/> <อินพุต type = "submit" value = "อัปโหลด"/> </form> <font color = "red" size = "6"> ใช้เครื่องมืออัปโหลดไฟล์ Apache แบบฟอร์ม): enctype = แอปพลิเคชัน/x-www-form-urlencoded (ค่าเริ่มต้น)-> <!-post2 (อัพโหลดไฟล์ฟอร์มไฟล์): Enctype = multipart/form-data: multipart (ไม่เพียง แต่ไฟล์ แต่ยังรวมถึง encty = "<%= request.getContextPath () type = "file" name = "file"/> <!-post2 (อัพโหลดฟอร์มไฟล์)-> <br/> คำอธิบายไฟล์: <อินพุต type = "text" name = "desc"/> <!-post1 (แบบฟอร์มปกติ)-> <br/> <br/> ไฟล์ 2: value = "upload"/> </form> </body> </html>
ทำความเข้าใจกับชั้นล่างของบอร์ดการเปลี่ยนแปลง
แพ็คเกจ cn.hncu.servlet; นำเข้า java.io.bufferedreader; นำเข้า java.io.ioexception; นำเข้า java.io.inputstream; นำเข้า java.io.InputStreamReader; นำเข้า Java.io.printwriter; นำเข้า Javax.servlet.servletexception; javax.servlet.http.httpservletrequest; นำเข้า Javax.servlet.http.httpservletResponse; คลาสสาธารณะอัพโหลด 0Servlet ขยาย httpservlet {โมฆะสาธารณะ dopost (httpservletrequest คำขอ ใน = request.getInputStream (); bufferedReader br = bufferedReader ใหม่ (ใหม่ inputStreamReader (ใน)); สายสตริง; ในขณะที่ ((line = br.readline ())! = null) {system.out.println (บรรทัด); -ใช้เครื่องมืออัปโหลดไฟล์ Apache เพื่อใช้งานการอัปโหลดไฟล์
แพ็คเกจ cn.hncu.servlet; นำเข้า java.io.file; นำเข้า java.io.ioexception; นำเข้า java.io.printwriter; นำเข้า java.util.list; นำเข้า java.util.uuid; นำเข้า Javax.servlet.servletexception; javax.servlet.http.httpservletrequest; นำเข้า Javax.servlet.http.httpservletResponse; นำเข้า org.apache.commons.fileupload.fileitem; นำเข้า org.apache.Commons.fileupload org.apache.commons.fileupload.disk.diskfileitemfactory นำเข้า org.apache.commons.fileupload.servlet.servletfileupload; นำเข้า org.apache.commons.io.fileutils; httpservletResponse การตอบสนอง) พ่น servletexception, ioexception {response.setContentType ("ข้อความ/html"); PrintWriter out = response.getWriter (); out.println ("<! doctype html สาธารณะ/"-// w3c // dtd html 4.01 transitional // en/">"); out.println ("<html>"); out.println ("<head> <title> a servlet </title> </head>"); out.println ("<body>"); out.print ("ไม่สนับสนุนรับการอัปโหลด ... . ... "); out.println ("</body>"); out.println ("</html>"); out.flush (); out.close (); } โมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception {// บนเซิร์ฟเวอร์ระบุไดเรกทอรีสำหรับไฟล์สตริงที่อัปโหลดทั้งหมด = getServletContext () getRealPath ("/upload"); System.out.println ("Path:"+Path); ไฟล์ dir = ไฟล์ใหม่ (พา ธ ); if (! dir.exists ()) {dir.mkdirs (); } // สร้างโรงงานที่ใช้ฮาร์ดดิสก์ // diskfileitemfactory ดิสก์ = ใหม่ diskfileitemfactory (); // ตั้งค่าไดเรกทอรีชั่วคราว (ขอแนะนำให้ออกแบบไดเรกทอรีชั่วคราวมิฉะนั้นจะใช้ไดเรกทอรีชั่วคราวของระบบ) //disk.setRepository (ไฟล์ใหม่ ("d:/a")); // 3. ตั้งค่าขนาดบัฟเฟอร์สำหรับการเขียนข้อมูลไปยังฮาร์ดดิสก์ดิสก์ SetsizEthreshold (1024*4); // เมื่อไฟล์มีขนาดใหญ่กว่าการตั้งค่านี้ไฟล์ชั่วคราวจะถูกสร้างขึ้นในไดเรกทอรีชั่วคราว // ตั้งค่าขนาดบัฟเฟอร์ไฟล์ชั่วคราว-บัฟเฟอร์ 8K ที่อยู่ไฟล์ชั่วคราว diskfileitemfactory f = ใหม่ diskfileitemfactory (1024*8 ไฟล์ใหม่ ("d:/a")); // เครื่องมืออัปโหลด-สร้างวัตถุสำหรับการแยกวิเคราะห์ servletFileUpload อัปโหลด = ใหม่ servletFileUpload (F); upload.setFilesizeMax (1024*1024*5); // ตั้งค่าไฟล์เดียวที่อัปโหลดสูงสุดเป็น 5m // ตั้งค่าขนาดสูงสุดของไฟล์ที่อัปโหลด หากเป็นหลายไฟล์มันเป็นผลรวมของหลายไฟล์ที่สูงถึง 8m upload.setSizeMax (1024*1024*8); // ตั้งค่าผลรวมของขนาดไฟล์ที่อัปโหลดทั้งหมดสูงสุด 8m // ใช้เครื่องมือแยกวิเคราะห์เพื่อแยกวิเคราะห์ลอง {list <fileitem> list = upload.parserequest (คำขอ); สำหรับ (fileitem fi: list) {system.out.println ("ประเภทเนื้อหาไฟล์:"+fi.getContentType ()); // ประเภทไฟล์ประเภทไฟล์: ข้อความ/ระบบธรรมดา. ext = fi.getName (). substring (fi.getName (). lastIndexof (".")); //. สตริง txt uuid = uuid.randomuuid (). toString () แทนที่ ("-", ""); String filename = uuid+ext; // fileutils.copyInputStreamTofile (fi.getInputStream (), ไฟล์ใหม่ ("d: /a/d/a.txt")); // เขียนมันตาย // fi.getInputStream () เป็นไฟล์ข้อมูลไฟล์จริง ไฟล์ (พา ธ+"/"+ชื่อไฟล์)); // เขียนมันมีชีวิตอยู่}} catch (fileuploadexception e) {e.printstacktrace (); - จัดเก็บไฟล์ที่อัปโหลดในสถานที่นี้
อัปโหลดข้อมูล:
อัปโหลดผลลัพธ์:
ใช้เครื่องมืออัปโหลดไฟล์ Apache เพื่อให้ได้ไฟล์อัปโหลด 2 (แก้ชื่อไฟล์ที่อ่านไม่ออก)
แพ็คเกจ cn.hncu.servlet; นำเข้า java.io.file; นำเข้า java.io.ioexception; นำเข้า java.io.printwriter; นำเข้า java.util.list; นำเข้า java.util.uuid; นำเข้า Javax.servlet.servletexception; javax.servlet.http.httpservletrequest; นำเข้า Javax.servlet.http.httpservletResponse; นำเข้า org.apache.commons.fileupload.fileitem; นำเข้า org.apache.Commons.fileupload org.apache.commons.fileupload.disk.diskfileitemfactory; นำเข้า org.apache.commons.fileupload.servlet.servletfileupload; นำเข้า org.apache.commons.io.fileutils; httpservletResponse การตอบสนอง) พ่น servletexception, ioexception {response.setContentType ("ข้อความ/html"); // หากเป็นแบบฟอร์มที่มีไฟล์ที่อัปโหลด (post2) ละครสามารถตั้งค่าการเข้ารหัสในชื่อไฟล์ของไฟล์ที่อัปโหลด (แก้รหัสภาษาจีนที่อ่านไม่ออก) // แต่ไม่สามารถแก้รหัสส่วนประกอบแบบฟอร์มทั่วไปของจีนในโหมด post2 out = response.getWriter (); out.println ("<! doctype html สาธารณะ/"-// w3c // dtd html 4.01 transitional // en/">"); out.println ("<html>"); out.println ("<head> <title> a servlet </title> </head>"); out.println ("<body>"); out.print ("ไม่สนับสนุนรับการอัปโหลด ... . ... "); out.println ("</body>"); out.println ("</html>"); out.flush (); out.close (); } โมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception {// ขั้นตอนที่ 1 // แบบฟอร์มทั่วไป (post1) ประโยคต่อไปนี้สามารถตั้งค่าการเข้ารหัสเนื้อหาขององค์ประกอบแบบฟอร์มทั่วไป // หากเป็นแบบฟอร์มที่มีไฟล์ที่อัปโหลด (post2) ประโยคนี้สามารถตั้งค่าการเข้ารหัสในชื่อไฟล์ของไฟล์ที่อัปโหลดได้เท่านั้น แต่มันไม่สามารถแก้ปัญหารหัสที่อ่านไม่ออกขององค์ประกอบแบบฟอร์มทั่วไป (ไม่สามารถตั้งค่าการเข้ารหัส) // บนเซิร์ฟเวอร์ระบุไดเรกทอรีสำหรับไฟล์สตริงไฟล์ที่อัปโหลดทั้งหมด = getServletContext () getRealPath ("/อัปโหลด"); System.out.println ("Path:"+Path); ไฟล์ dir = ไฟล์ใหม่ (พา ธ ); if (! dir.exists ()) {dir.mkdirs (); } // ตั้งค่าบัฟเฟอร์ไฟล์ชั่วคราว-8K บัฟเฟอร์, ที่อยู่ไฟล์ชั่วคราวที่อยู่ไฟล์ DiskFileItemFactory F = ใหม่ diskFileItemFactory (1024*8, ไฟล์ใหม่ ("d:/a")); // เครื่องมืออัปโหลด servletFileUpload upload = ใหม่ servletFileUpload (f); upload.setFilesizeMax (1024*1024*5); // ตั้งค่าไฟล์เดียวที่อัปโหลดสูงสุดเป็น 5m upload.setSizemax (1024*1024*8); // ตั้งค่าผลรวมของขนาดไฟล์ที่อัปโหลดทั้งหมดเป็น 8m // ใช้เครื่องมือแยกวิเคราะห์เพื่อแยกวิเคราะห์ลอง {list <fileitem> list = upload.parserequest (คำขอ); สำหรับ (fileitem fi: list) {if ((fi.isformfield ())) {// ถ้ามันเป็นส่วนประกอบรูปแบบปกติ: ช่องทำเครื่องหมาย, วิทยุ, รหัสผ่าน ... // string desc = fi.getString (); System.out.println ("fi.getString ():"+fi.getString ()); // สตริงขั้นตอนที่สอง desc = fi.getString ("UTF-8"); // ประโยคนี้ตั้งค่าการเข้ารหัสเนื้อหาขององค์ประกอบแบบฟอร์มทั่วไป System.out.println ("หลังจากการเข้ารหัส:"+desc); } else {string ext = fi.getName (). substring (fi.getName (). lastIndexof (".")); //. txt string uuid = uuid.randomuuid (). toString (). แทนที่ ("-", "); String filename = uuid+ext; //fi.getInputStream () เป็นข้อมูลไฟล์จริง fileutils.copyInputStreamTofile (fi.getInputStream (), ไฟล์ใหม่ (พา ธ+"/"+ชื่อไฟล์)); // เขียนมัน}}} catch (fileuploadexception e) {e.printstacktrace () -อัปโหลดข้อมูล:
อัปโหลดผลลัพธ์:
ใช้เครื่องมืออัปโหลดไฟล์ Apache เพื่อให้ได้ไฟล์อัปโหลด 3 (การแยกไฟล์)
เพิ่มประสิทธิภาพการจัดเก็บไฟล์ด้วยไดเรกทอรีแฮช:
ไดเรกทอรีแฮชเป็นวิธีการเพิ่มประสิทธิภาพการจัดเก็บไฟล์ ไม่ว่าจะเป็น Windows หรือ Linux ไม่ว่าจะเป็น NTFS หรือ EXT3 จำนวนรายการที่สามารถรองรับได้ในแต่ละไดเรกทอรีมี จำกัด
ไม่ใช่ว่าไม่สามารถบันทึกได้ แต่เมื่อจำนวนโครงการมีขนาดใหญ่เกินไปความเร็วในการจัดทำดัชนีไฟล์จะลดลง
ดังนั้นจึงจำเป็นต้องชั่งน้ำหนักจำนวนไฟล์ที่ควรบันทึกไว้ในไดเรกทอรี การประหยัดมากเกินไปจะส่งผลกระทบต่อประสิทธิภาพในขณะที่การประหยัดน้อยเกินไปจะทำให้ไดเรกทอรีมากเกินไปและเสียพื้นที่ ดังนั้นเมื่อบันทึกชุดไฟล์ขนาดใหญ่
มีอัลกอริทึมที่สามารถ "ทำลาย" ไฟล์ได้อย่างสม่ำเสมอในไดเรกทอรีย่อยที่แตกต่างกันเพื่อปรับปรุงความเร็วดัชนีของแต่ละระดับ อัลกอริทึมนี้คือแฮช MD5, SHA1 ที่ใช้กันทั่วไปสามารถใช้เป็นไดเรกทอรีแฮชได้ MD5 ยังใช้ในเซสชั่นของฉันเพื่อรับตัวเลขแรกและตัวเลขที่เก้าของ SessionID ซึ่งถือเป็นเส้นทางแฮชสองระดับ กล่าวคือระบบกระจายไฟล์เซสชันทั้งหมดเป็น 16 × 16 = 256 ไดเรกทอรีย่อย สมมติว่าการบันทึกไฟล์ 1,000 ไฟล์ในแต่ละไดเรกทอรีของ Linux สามารถบรรลุอัตราส่วนประสิทธิภาพพื้นที่ที่ดีที่สุดระบบสามารถมีไฟล์เซสชัน 256,000 ไฟล์ในเวลาเดียวกัน
แพ็คเกจ cn.hncu.servlet; นำเข้า java.io.file; นำเข้า java.io.ioexception; นำเข้า java.io.printwriter; นำเข้า java.util.list; นำเข้า java.util.uuid; นำเข้า Javax.servlet.servletexception; javax.servlet.http.httpservletrequest; นำเข้า Javax.servlet.http.httpservletResponse; นำเข้า org.apache.commons.fileupload.fileitem; นำเข้า org.apache.Commons.fileupload org.apache.commons.fileupload.progresslistener; นำเข้า org.apache.commons.fileupload.disk.diskfileitemfactory; นำเข้า org.apache.Commons.fileupload.servlet.servletFileUpload; {โมฆะสาธารณะ DOGET (คำขอ httpservletRequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception {response.setContentType ("ข้อความ/html"); // หากเป็นแบบฟอร์มที่มีไฟล์ที่อัปโหลด (post2) ละครสามารถตั้งค่าการเข้ารหัสในชื่อไฟล์ของไฟล์ที่อัปโหลด (แก้รหัสภาษาจีนที่อ่านไม่ออก) // แต่ไม่สามารถแก้รหัสส่วนประกอบแบบฟอร์มทั่วไปของจีนในโหมด post2 out = response.getWriter (); out.println ("<! doctype html สาธารณะ/"-// w3c // dtd html 4.01 transitional // en/">"); out.println ("<html>"); out.println ("<head> <title> a servlet </title> </head>"); out.println ("<body>"); // รับส่วนหลังจาก "?" หมายเลขใน URL ใน Method // http: // localhost: 8080/servletdemo3/อัปโหลด? name = jack & sex = male string qstr = request.getQueryString (); System.out.println ("qstr:"+qstr); // qstr: name = jack & sex = male out.print ("ไม่สนับสนุนรับอัปโหลด ... ."); out.println ("</body>"); out.println ("</html>"); out.flush (); out.close (); } โมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception {response.setContentType ("text/html; charset = utf-8"); PrintWriter out = response.getWriter (); // 1 Anti-Black: Front-end ของการป้องกันถูกส่งโดยใช้วิธีการ post1 // วิธี 1 /* ประเภทสตริง = request.getContentType (); if (! type.contains ("multipart/form-data")) {out.println ("การส่งแบบฟอร์มที่ไม่รองรับ"); กลับ; }*/// วิธีการ 2 บูลีนบู = servletFileUpload.ismultipartContent (คำขอ); if (! boo) {out.println ("การส่งแบบฟอร์มที่ไม่รองรับ"); กลับ; } // ขั้นตอนที่ 1 // ฟอร์มแบบฟอร์มสามัญ (post1) ประโยคต่อไปนี้สามารถตั้งค่าการเข้ารหัสเนื้อหาขององค์ประกอบแบบฟอร์มสามัญ (สามารถแก้ปัญหาปัญหาที่อ่านไม่ออกภาษาจีนได้) คำขอ Setcharacterencoding ("UTF-8"); // หากเป็นแบบฟอร์มที่มีไฟล์ที่อัปโหลด (post2) ประโยคนี้สามารถตั้งค่าการเข้ารหัสในชื่อไฟล์ของไฟล์ที่อัปโหลดได้เท่านั้น แต่มันไม่สามารถแก้ปัญหารหัสที่อ่านไม่ออกขององค์ประกอบแบบฟอร์มทั่วไป (ไม่สามารถตั้งค่าการเข้ารหัส) // บนเซิร์ฟเวอร์ระบุไดเรกทอรีสำหรับไฟล์สตริงไฟล์ที่อัปโหลดทั้งหมด = getServletContext () getRealPath ("/อัปโหลด"); System.out.println ("Path:"+Path); ไฟล์ dir = ไฟล์ใหม่ (พา ธ ); if (! dir.exists ()) {dir.mkdirs (); } // ตั้งค่าบัฟเฟอร์ไฟล์ชั่วคราว-8K บัฟเฟอร์, ที่อยู่ไฟล์ชั่วคราวที่อยู่ไฟล์ DiskFileItemFactory F = ใหม่ diskFileItemFactory (1024*8, ไฟล์ใหม่ ("d:/a")); // เครื่องมืออัปโหลด servletFileUpload upload = ใหม่ servletFileUpload (f); upload.setFilesizeMax (1024*1024*5); // ตั้งค่าไฟล์เดียวที่อัปโหลดสูงสุดเป็น 5m upload.setSizemax (1024*1024*8); // ตั้งค่าผลรวมสูงสุดของขนาดไฟล์ที่อัปโหลดทั้งหมดคือ 8m // ▲ 4 อัปโหลดความคืบหน้าการฟังการอัปโหลด SetProgressListener (ใหม่ ProgressionListener () {ส่วนตัวสองครั้งก่อน = 0d; @override // พารามิเตอร์ 1: จำนวน 1) pcontentlength, int pitems) {double d = 1.0*pbyteread/pcontentlength*100; // ใช้เครื่องมือแยกวิเคราะห์เพื่อแยกวิเคราะห์ลอง {list <fileItem> list = upload.parserequest (คำขอ); สำหรับ (fileitem fi: list) {if ((fi.isformfield ())) {// ถ้ามันเป็นส่วนประกอบรูปแบบปกติ: ช่องทำเครื่องหมาย, วิทยุ, รหัสผ่าน ... // string desc = fi.getString (); System.out.println ("fi.getString ():"+fi.getString ()); // สตริงขั้นตอนที่สอง desc = fi.getString ("UTF-8"); // ประโยคนี้ตั้งค่าการเข้ารหัสเนื้อหาขององค์ประกอบส่วนประกอบรูปแบบปกติ System.out.println ("การเข้ารหัส:"+desc); } else {// protect: กรองส่วนประกอบไฟล์เปล่าที่ไม่ได้เลือกถ้า (fi.getSize () <= 0) {ดำเนินการต่อ; // อ่านไฟล์ถัดไป} system.out.println ("ไฟล์ประเภทไฟล์:"+fi.getContentType (); c: /users/adl1/desktop/a.txt string ext = fi.getName (). substring (fi.getName (). lastIndexof (".")); //. สตริง txt uuid = uuid.randomuuid () String filename = uuid+ext; // ไฟล์ไดเรกทอรีเทคโนโลยีการทำลายสตริง dir1 = integer.tohexstring (uuid.hashcode () & 0x0f); String dir2 = integer.tohexstring ((uuid.hashCode () & 0xf0) >> 4); //fi.getInputStream () เป็นข้อมูลไฟล์จริง fileutils.copyInputStreamTofile (fi.getInputStream (), ไฟล์ใหม่ (เส้นทาง+"/"+dir1+"/"+dir2+"/"+filename); -ทำลายข้อความ:
ทำลายผลลัพธ์:
ไฟล์ 1:
ไฟล์ 2:
แสดงให้เห็นถึงหลักการของความคืบหน้าการอัปโหลด
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น