การอัปโหลดไฟล์เป็นเรื่องธรรมดามากในเว็บแอปพลิเคชัน มันง่ายมากที่จะใช้ฟังก์ชั่นการอัปโหลดไฟล์ในสภาพแวดล้อม JSP เนื่องจากมีส่วนประกอบการอัปโหลดไฟล์จำนวนมากที่พัฒนาขึ้นใน Java บนอินเทอร์เน็ต บทความนี้ใช้ส่วนประกอบคอมมอนส์-ฟิลด์อัปโหลดเป็นตัวอย่างในการเพิ่มฟังก์ชั่นการอัปโหลดไฟล์ไปยังแอปพลิเคชัน JSP
ส่วนประกอบ Common-Fileupload เป็นหนึ่งในโครงการโอเพ่นซอร์สของ Apache และสามารถดาวน์โหลดได้จาก http://jakarta.apache.org/commons/fileupload/
ส่วนประกอบนี้ช่วยให้คุณสามารถอัปโหลดไฟล์ทีละไฟล์ได้ทีละไฟล์และสามารถ จำกัด ขนาดไฟล์
หลังจากดาวน์โหลดแล้วคลายซิปแพ็คเกจ ZIP และคัดลอก Commons-FilePiLoad-1.0.jar ไปยัง WebApps ของ Tomcat ภายใต้ Webappweb-inflib ของคุณ หากไดเรกทอรีไม่มีอยู่โปรดสร้างไดเรกทอรีของคุณเอง
สร้าง servlet ใหม่: upload.java สำหรับการอัปโหลดไฟล์:
นำเข้า Java.io.*; นำเข้า Java.util.*; นำเข้า Javax.servlet.*; นำเข้า Javax.servlet.http.*; นำเข้า org.apache.commons.fileupload.*; การอัปโหลดคลาสสาธารณะขยาย httpservlet {สตริงส่วนตัว uploadPath = "c: อัปโหลด"; // ไดเรกทอรีสำหรับการอัปโหลดไฟล์สตริงส่วนตัว temppath = "c: uploadtmp"; // ไดเรกทอรีไฟล์ชั่วคราวโมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น IOException, servletexception {}}ในวิธี DOPOST () เมื่อ servlet ได้รับคำขอโพสต์ที่ออกโดยเบราว์เซอร์จะตระหนักถึงการอัปโหลดไฟล์ นี่คือรหัสตัวอย่าง:
โมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น IOException, servletexception {ลอง {diskfileupload fu = ใหม่ diskfileupload (); // ตั้งค่าขนาดไฟล์สูงสุดนี่คือ 4MBFU.SetSizemax (4194304); // ตั้งค่าขนาดบัฟเฟอร์นี่คือ 4kbfu.setsizethreshold (4096); // ตั้งค่าไดเรกทอรีชั่วคราว: FU.SetRepositoryPath (Temppath); // รับไฟล์ทั้งหมด: รายการ fileItems = fu.parserequest (คำขอ); ตัววนซ้ำ i = fileitems.iterator (); // ประมวลผลแต่ละไฟล์ตามลำดับ: ในขณะที่ (i.hasNext ()) {fileItem fi = (fileItem) i.next (); // รับชื่อไฟล์ชื่อไฟล์รวม PATH: String filename = fi.getName (); // ที่นี่คุณสามารถบันทึกข้อมูลผู้ใช้และไฟล์ // ... // เขียนไปยังไฟล์ชื่อไฟล์ tentative คือ a.txt และชื่อไฟล์สามารถแยกได้จากชื่อไฟล์: fi.write (ไฟล์ใหม่ (uploadpath + "a.txt")); }} catch (Exception e) {// คุณสามารถข้ามไปที่หน้าข้อผิดพลาด}}หากคุณต้องการอ่านโฟลเดอร์อัปโหลดที่ระบุในไฟล์กำหนดค่าคุณสามารถเรียกใช้งานได้ในเมธอด init ():
public void init () พ่น servletexception {uploadpath = .... temppath = .... // ถ้าโฟลเดอร์ไม่มีอยู่มันจะถูกสร้างขึ้นโดยอัตโนมัติ: ถ้า (! ไฟล์ใหม่ (uploadPath) .isdirectory ()) ไฟล์ใหม่ (uploadPath) .MkDirs (); if (! ไฟล์ใหม่ (temppath) .isdirectory ()) ไฟล์ใหม่ (temppath) .mkdirs (); -รวบรวม servlet ระวังเพื่อระบุ classpath ตรวจสอบให้แน่ใจว่าได้รวม Commons-upload-1.0.jar และ tomcatcommonlibservlet-api.jar
กำหนดค่า servlet ใช้ notepad เพื่อเปิด tomcatwebapps สำหรับ webappweb-infweb.xml ของคุณและสร้างใหม่ถ้าไม่
การกำหนดค่าทั่วไปมีดังนี้:
〈? xml version = "1.0" การเข้ารหัส = "ISO-8859-1" 2.3 // en "" http://java.sun.com/dtd/web-app_2_3 ervlet-Class> 〈servlet-mapping 〈servlet-name> อัปโหลด 〈/servlet-name> 〈url-pattern〉/fileupload 〈/url-pattern 〈/servlet-mapping 〈/web-app 〈
หลังจากกำหนดค่า servlet ให้เริ่ม Tomcat และเขียนการทดสอบ HTML อย่างง่าย:
〈form action = "fileupload" method = "post" enctype = "multipart/form-data" name = "form1"> 〈input type = "file" name = "file"> 〈input type = "subment" name = "submit" value = "upload">
หมายเหตุ action = "fileupload" โดยที่ fileupload เป็น URL-pattern ที่ระบุเมื่อกำหนดค่า servlet
นี่คือรหัสสำหรับกุ้ง:
การอัปโหลดนี้ใช้งานง่ายกว่า SmartUpload มาก มันถูกสร้างขึ้นอย่างสมบูรณ์โดยฉันไบต์ทีละคนซึ่งแตกต่างจาก smartupload ที่มีข้อบกพร่องมากมาย
วิธีการโทร:
อัปโหลดขึ้น = ใหม่อัปโหลด (); Up.init (คำขอ); /** สามารถเรียก setSavedir (สตริง savedir); ตั้งค่า PATH SAVE และ CALL SETMAXFILESIZE (ขนาดยาว) เพื่อตั้งค่าไบต์สูงสุดของไฟล์ที่อัปโหลด เรียกใช้ setTagfileName (สตริง) เพื่อตั้งค่าชื่อของไฟล์หลังจากอัปโหลด (ใช้ได้เฉพาะสำหรับไฟล์แรก)*/up uploadfile ();
จากนั้นสตริง [] ชื่อ = up.getFileName (); รับชื่อไฟล์ที่อัปโหลดเส้นทางสัมบูรณ์ของไฟล์ควรเป็น
บันทึกไดเรกทอรีที่บันทึกไว้ savedir+"/"+ชื่อ [i];
คุณสามารถรับข้อความที่อัปโหลดหรือ up.getParametervalues ("ยื่น") ผ่าน Up.getParameter ("ฟิลด์");
รับค่าของฟิลด์ที่มีชื่อเดียวกันเช่นช่องทำเครื่องหมายหลายช่อง
ลองคนอื่นด้วยตัวเอง
ซอร์สโค้ดมีดังนี้: ______________________________________________________________________________
แพ็คเกจ com.inmsg.beans; นำเข้า Java.io.*; นำเข้า Java.util.*; นำเข้า Javax.servlet.*; นำเข้า Javax.servlet.http.*; การอัปโหลดคลาสสาธารณะ {สตริงส่วนตัว savedir = "."; // พา ธ เพื่อบันทึกไฟล์สตริงส่วนตัว contentType = ""; // เอกสารประเภทสตริงส่วนตัว charset = ""; // ตัวอักษรตั้งค่า arraylist ส่วนตัว tmpfilename = new ArrayList (); // โครงสร้างข้อมูลชั่วคราวสำหรับการจัดเก็บชื่อไฟล์พารามิเตอร์ hashtable ส่วนตัว = new hashtable (); // โครงสร้างข้อมูลที่เก็บชื่อพารามิเตอร์และค่าบริบท servletContext ส่วนตัว; // บริบทของโปรแกรมใช้เพื่อเริ่มต้นคำขอ httpservletrequest ส่วนตัว; // อินสแตนซ์ที่ใช้ในการส่งผ่านวัตถุประสงค์ของวัตถุสตริงส่วนตัว = ""; // ตัวคั่นข้อมูลหน่วยความจำส่วนตัว int len = 0; // ความยาวไบต์อ่านจริงจากภายในทุกครั้งที่คิวรีสตริงส่วนตัว จำนวน int ส่วนตัว; // จำนวนไฟล์ที่อัปโหลดทั้งหมดสตริงส่วนตัว [] ชื่อไฟล์; // อัปโหลดชื่อไฟล์อาร์เรย์ส่วนตัวยาว maxfilesize = 1024 * 1024 * 10; // ไฟล์สูงสุดอัพโหลดไบต์; สตริงส่วนตัว tagfileName = ""; เป็นโมฆะสุดท้ายสาธารณะ init (คำขอ httpservletrequest) พ่น servletexception {this.request = คำขอ; Boundary = request.getContentType (). substring (30); // รับตัวคั่นข้อมูลตัวคั่นข้อมูลในหน่วยความจำ = request.getQueryString (); } สตริงสาธารณะ getParameter (สตริง s) {// ใช้เพื่อรับค่าพารามิเตอร์ของฟิลด์ที่ระบุ, request.getParameter (สตริง s) ถ้า (parameter.isempty ()) {return null; } return (string) parameter.get (s); } สตริงสาธารณะ [] getParamEterValues (สตริง s) {// ใช้เพื่อรับอาร์เรย์พารามิเตอร์ที่ระบุด้วยฟิลด์ชื่อเดียวกัน, request.getParameterValues (String s) ArrayList al = new ArrayList (); if (parameter.isempty ()) {return null; } การแจงนับ e = parameter.keys (); ในขณะที่ (e.hasmoreElements ()) {สตริงคีย์ = (สตริง) e.nextElement (); if (-1! = key.indexof (S + "| | |||||||||||") || key.equals (s)) {al.add (parameter.get (key)); }} if (al.size () == 0) {return null; } string [] value = สตริงใหม่ [al.size ()]; สำหรับ (int i = 0; i 〈value.length; i ++) {value [i] = (string) al.get (i); } ค่าส่งคืน; } สตริงสาธารณะ getQueryString () {return querystring; } public int getCount () {นับคืน; } สตริงสาธารณะ [] getFilename () {return filename; } โมฆะสาธารณะ setMaxFilesize (ขนาดยาว) {maxFilesize = size; } โมฆะสาธารณะ setTagfileName (ชื่อไฟล์สตริง) {tagFileName = filename; } โมฆะสาธารณะ setSavedir (สตริง savedir) {// ตั้งค่าเส้นทางเพื่อบันทึกสำหรับการอัปโหลดไฟล์ this.savedir = savedir; ไฟล์ testDir = ไฟล์ใหม่ (savedir); // เพื่อให้แน่ใจว่าไดเรกทอรีมีอยู่หากไม่มีให้สร้างไดเรกทอรีถ้า (! testdir.exists ()) {testdir.mkdir (); }} โมฆะสาธารณะ setCharSet (สตริง charset) {// ตั้งค่าตัวละครตั้งค่า this.charset = charset; } บูลีนสาธารณะ uploadfile () พ่น servletexception, ioexception {// วิธีการอัปโหลดที่เรียกโดยผู้ใช้ setCharset (request.getCharacterencoding ()); return uploadfile (request.getInputStream ()); } บูลีนส่วนตัว uploadfile (servletInputStream servletInputStream) พ่น // วิธีหลักในการรับข้อมูลการจัดเก็บส่วนกลาง servletexception, ioException {สตริงบรรทัด = null; ไบต์ [] บัฟเฟอร์ = ไบต์ใหม่ [256]; ในขณะที่ ((line = readline (บัฟเฟอร์, servletInputStream, charset))! = null) {if (line.startswith ("เนื้อหา-การจัดสรร: form-data;"))) {int i = line.indexof ("filename ="); if (i〉 = 0) {// ถ้ามี filename = ในคำอธิบายในตัวคั่นนั่นหมายความว่ามันเป็นเนื้อหาที่เข้ารหัสของสตริงไฟล์ fname = getFilename (บรรทัด); if (fname.equals ("")) {ดำเนินการต่อ; } if (count == 0 && tagfileName.length ()! = 0) {string ext = fname.substring ((fname.lastindexof (".") + 1)); fname = tagfilename + "." + ext; } tmpfilename.add (fname); นับ ++; ในขณะที่ ((line = readline (บัฟเฟอร์, servletInputStream, charset))! = null) {ถ้า (line.length () 〈= 2) {break; }} ไฟล์ f = ไฟล์ใหม่ (savedir, fname); fileOutputStream dos = ใหม่ fileOutputStream (f); ขนาดยาว = 0l; ในขณะที่ ((line = readline (บัฟเฟอร์, servletInputStream, null))! = null) {if (line.indexof (ขอบเขต)! = -1) {break; } size += len; if (size〉 maxfilesize) {โยน ioexception ใหม่ ("ไฟล์เกิน" + maxfilesize + "ไบต์!"); } dos.write (บัฟเฟอร์, 0, len); } dos.close (); } else {// มิฉะนั้นมันเป็นเนื้อหาของคีย์สตริงการเข้ารหัสฟิลด์ = getKey (บรรทัด); ค่าสตริง = ""; ในขณะที่ ((line = readline (บัฟเฟอร์, servletInputStream, charset))! = null) {ถ้า (line.length () 〈= 2) {break; }} ในขณะที่ ((line = readline (บัฟเฟอร์, servletInputStream, charset))! = null) {if (line.indexof (ขอบเขต)! = -1) {break; } ค่า += บรรทัด; } put (key, value.trim (), พารามิเตอร์); }}} if (queryString! = null) {string [] แต่ละ = split (querystring, "&"); สำหรับ (int k = 0; k 〈แต่ละความยาว; k ++) {string [] nv = แยก (แต่ละ [k], "="); if (nv.length == 2) {put (nv [0], nv [1], พารามิเตอร์); }}} filename = สตริงใหม่ [tmpfilename.size ()]; สำหรับ (int k = 0; k 〈filename.length; k ++) {filename [k] = (สตริง) tmpfilename.get (k); // เทชื่อไฟล์ชั่วคราวใน ArrayList ลงในข้อมูลเพื่อให้ผู้ใช้โทร} ถ้า (filename.length == 0) {return false; // หากข้อมูลชื่อไฟล์ว่างเปล่าหมายความว่าไม่มีการอัปโหลดไฟล์} ส่งคืนจริง } โมฆะส่วนตัวใส่ (คีย์สตริง, ค่าสตริง, hashtable ht) {ถ้า (! ht.containskey (คีย์)) {ht.put (คีย์, ค่า); } else {// หากคุณมีคีย์ที่มีชื่อเดียวกันอยู่แล้วคุณต้องเปลี่ยนชื่อคีย์ปัจจุบัน ในเวลาเดียวกันโปรดระวังอย่าให้สร้างชื่อเดียวกันกับคีย์ลอง {thread.currentthread () นอนหลับ (1); // เพื่อไม่ให้สร้างคีย์ที่เหมือนกันสองปุ่มใน MS} catch (Exception E) {} คีย์ += "|||||||||||| | + System.currentTimemillis (); ht.put (คีย์, ค่า); }}/* การเรียก servletInputStream.readline (byte [] b, int ออฟเซ็ต, ความยาว) ซึ่งอ่านบรรทัดจากสตรีม servletInputStream ไปยังอาร์เรย์ไบต์ที่ระบุ เพื่อให้แน่ใจว่าสามารถรองรับบรรทัดไบต์ [] B ไม่ควรน้อยกว่า 256 ในการอ่านใหม่ใหม่ตัวแปรสมาชิกเลนถูกเรียกไปยังจำนวนไบต์ที่อ่านจริง (บางบรรทัดน้อยกว่า 256) เมื่อเขียนเนื้อหาไฟล์ไบต์ของความยาวเลนควรเขียนจากอาร์เรย์ไบต์แทนความยาวทั้งหมดของไบต์ [] อย่างไรก็ตามวิธีการที่เขียนใหม่จะส่งคืนสตริงเพื่อวิเคราะห์เนื้อหาจริงและไม่สามารถส่งคืน LEN ได้ดังนั้น Len จึงถูกตั้งค่าเป็นตัวแปรสมาชิกและกำหนดความยาวจริงให้กับมันในแต่ละครั้งที่การดำเนินการอ่าน กล่าวคือเมื่อประมวลผลเนื้อหาของไฟล์ข้อมูลจะต้องถูกส่งคืนในรูปแบบของสตริงเพื่อวิเคราะห์เครื่องหมายเริ่มต้นและจุดสิ้นสุดและเขียนลงในสตรีมเอาต์พุตไฟล์ในรูปแบบของไบต์ [] ในเวลาเดียวกัน */สตริงส่วนตัว readline (byte [] lineByte, servletInputStream servletInputStream, สตริง charset) {ลอง {len = servletInputStream.readline (lineByte, 0, lineByte.length); if (len == -1) {return null; } if (charset == null) {ส่งคืนสตริงใหม่ (lineByte, 0, len); } else {ส่งคืนสตริงใหม่ (lineByte, 0, len, charset); }} catch (ข้อยกเว้น _ex) {return null; }} สตริงส่วนตัว getFileName (สายสตริง) {// แยกชื่อไฟล์ออกจากสตริงคำอธิบายถ้า (line == null) {return ""; } int i = line.indexof ("filename ="); line = line.substring (i + 9) .trim (); i = line.astIndexof (""); if (i 〈0 || i = line.length () - 1) {i = line.lastindexof ("/"); if (line.equals ("" "")) {return ""; } if (i 〈0 || i〉 = line.length () - 1) {return line; }} return line.substring (i + 1, line.length () - 1); } สตริงส่วนตัว getKey (สายสตริง) {// แยกชื่อฟิลด์ออกจากสตริงคำอธิบายถ้า (line == null) {return ""; } int i = line.indexof ("name ="); line = line.substring (i + 5) .trim (); return line.substring (1, line.length () - 1); } สตริงคงที่สาธารณะ [] split (String strob, เครื่องหมายสตริง) {ถ้า (strob == null) {return null; } stringTokenizer st = new StringTokenizer (strob, mark); ArrayList tmp = new ArrayList (); ในขณะที่ (st.hasmoretokens ()) {tmp.add (st.nexttoken ()); } string [] strarr = สตริงใหม่ [tmp.size ()]; สำหรับ (int i = 0; i 〈tmp.size (); i ++) {strarr [i] = (สตริง) tmp.get (i); } return strarr; }} การดาวน์โหลดนั้นง่ายมาก ตราบใดที่คุณดำเนินการดังนี้จะไม่มีปัญหาเกิดขึ้น ดาวน์โหลดโมฆะสาธารณะ (String FilePath, การตอบสนอง httpservletResponse, บูลีน isonline) พ่นข้อยกเว้น {ไฟล์ f = ไฟล์ใหม่ (filepath); if (! f.exists ()) {response.senderror (404, "ไม่พบไฟล์!"); กลับ; } bufferedInputStream br = ใหม่ bufferedInputStream (ใหม่ FileInputStream (F)); ไบต์ [] buf = ไบต์ใหม่ [1024]; int len = 0; Response.reset (); // มันสำคัญมากถ้า (isonline) {// ononopen method url u = url ใหม่ ("ไฟล์: ///"+filepath); Response.SetContentType (U.OpenConnection (). getContentType ()); Response.SetheAder ("เนื้อหา-การจัดสรร", "inline; filename ="+f.getName ()); // ชื่อไฟล์ควรเข้ารหัสเป็น utf-8} else {// วิธีการดาวน์โหลดบริสุทธิ์ response.setContentType ("แอปพลิเคชัน/x-msdownload"); Response.SetheAder ("เนื้อหา-การจัดสรร", "สิ่งที่แนบมา; ชื่อไฟล์ =" + f.getName ()); } outputStream out = response.getOutputStream (); ในขณะที่ ((len = br.read (buf))〉 0) out.write (buf, 0, len); br.close (); out.close (); -