1. ภาพรวมหลักสูตร
ในการพัฒนาระบบเว็บแอปพลิเคชันฟังก์ชั่นการอัปโหลดไฟล์เป็นฟังก์ชั่นที่พบบ่อยมาก วันนี้ส่วนใหญ่มาพูดคุยเกี่ยวกับการใช้งานทางเทคนิคที่เกี่ยวข้องของฟังก์ชั่นการอัปโหลดไฟล์ใน Javaweb ด้วยการพัฒนาเทคโนโลยีอินเทอร์เน็ตอย่างรวดเร็วข้อกำหนดประสบการณ์ของผู้ใช้สำหรับเว็บไซต์จะสูงขึ้นเรื่อย ๆ นอกจากนี้ยังมีจุดที่เป็นนวัตกรรมมากมายในเทคโนโลยีของฟังก์ชั่นการอัปโหลดไฟล์เช่นการอัปโหลดแบบอะซิงโครนัสการอัปโหลดการลากและวางการอัพโหลดการอัพโหลดการตรวจสอบความคืบหน้าไฟล์รูปขนาดย่อไฟล์ขนาดใหญ่การส่งไฟล์ขนาดใหญ่การส่งไฟล์ขนาดใหญ่ทันที ฯลฯ
พื้นฐานที่จำเป็นสำหรับหลักสูตรนี้:
ทำความเข้าใจเนื้อหาโปรโตคอล HTTP พื้นฐาน
เทคโนโลยีการดำเนินการสตรีม IO ขั้นพื้นฐาน
พื้นฐานของ servlet
ความรู้พื้นฐานเกี่ยวกับเทคโนโลยี JavaScript/JQuery
2. พื้นฐานของการอัปโหลดไฟล์
สำหรับการอัปโหลดไฟล์เบราว์เซอร์จะส่งไฟล์ไปยังฝั่งเซิร์ฟเวอร์ในรูปแบบของสตรีมระหว่างกระบวนการอัปโหลดและข้อมูลการสตรีมทั้งหมดจะถูกนำไปยังฝั่งเซิร์ฟเวอร์ด้วยคำขอ HTTP ดังนั้นรูปแบบของเนื้อหาที่ร้องขอเมื่ออัปโหลดไฟล์จะต้องเข้าใจโดยทั่วไป
หน้าอัปโหลดไฟล์:
<form action = "/itheheimaupload/uploadServlet" method = "post" enctype = "multipart/form-data"> โปรดเลือกไฟล์ที่อัปโหลด: <อินพุตประเภท = "ไฟล์" ชื่อ = "แนบ"/> <br/>
เนื้อหาคำขอ http:
3. พื้นหลัง Java ใช้ servlet เพื่อรับไฟล์
มันเป็นปัญหาถ้าคุณใช้ servlet เพื่อรับกระแสอินพุตของไฟล์ที่อัปโหลดแล้วแยกวิเคราะห์พารามิเตอร์คำขอในนั้น ดังนั้นโดยทั่วไปแล้วพื้นหลังเลือกที่จะใช้ส่วนประกอบอัพโหลดไฟล์ทั่วไป-FilePileLoad ซึ่งเป็นเครื่องมือโอเพ่นซอร์สของ Apache
// รหัสพื้นหลัง Java: Commons-FileUpload Component อัปโหลดไฟล์ Public Class UploadServlet ขยาย httpservlet {โมฆะสาธารณะ doget (httpservletrequest คำขอ, httpservletResponse การตอบสนอง) โยน servletexception, ioexception {// 1 กำหนดค่า Cache DiskFileItemFactory Factory = ใหม่ DiskFileItemFactory (1*1024*1024, ไฟล์ใหม่ ("C:/TempFiles/")); // 2 สร้าง servleFileUpload Object ServletFilePilePload SFU = ใหม่ servletFileUpload (โรงงาน); // แก้ปัญหาภาษาจีนของชื่อไฟล์ sfu.setheaderencoding ("UTF-8"); // 3 แก้ไขลอง {list <fileitem> list = sfu.parserequest (คำขอ); // แก้ไขเนื้อหาทั้งหมดถ้า (รายการ! = null) {สำหรับ (รายการ fileitem: รายการ) {// ตรวจสอบว่าเป็นพารามิเตอร์แบบฟอร์มปกติ (item.isformfield ()) value = item.getString ("UTF-8"); } else {// ไฟล์ถ้า (item.getName ()! = null &&! item.getName (). เท่ากับ ("")) {// บันทึกลงในฮาร์ดดิสก์เซิร์ฟเวอร์ fileutils.copyInputStreamTofile (item.getInputStream () ไฟล์ใหม่ (fileuploadexception e) {e.printstacktrace ();}} โมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) โยน servletexception, ioexception {doget (คำขอ, การตอบสนอง);}}}}}}}}}}4. ใช้ webPloader เพื่ออัปโหลดส่วนประกอบ
ที่ส่วนหน้าของหน้าอัปโหลดไฟล์เราสามารถเลือกที่จะใช้ส่วนประกอบการอัปโหลดที่มีประโยชน์มากขึ้นเช่น WebPloader ส่วนประกอบโอเพ่นซอร์สของ Baidu ส่วนประกอบนี้สามารถตอบสนองฟังก์ชั่นการอัปโหลดไฟล์ทุกวันเช่นการอัปโหลดแบบอะซิงโครนัสการอัปโหลดการลากและวางการวางการอัปโหลดอัปโหลดการตรวจสอบความคืบหน้าไฟล์รูปขนาดย่อไฟล์และแม้แต่จุดพักไฟล์ขนาดใหญ่เพื่อส่งต่อและส่งไฟล์ขนาดใหญ่ในวินาที
ดาวน์โหลดส่วนประกอบ webpload
http://fex.baidu.com/webuploader/ ดาวน์โหลดแพ็คเกจ webpload ที่เว็บไซต์อย่างเป็นทางการ webupload
โครงสร้างไดเรกทอรี webupload:
ตัวอย่างการอัปโหลดไฟล์พื้นฐาน (รวมถึงความคืบหน้าการอัปโหลด)
ส่วนหน้า
1.1 นำเข้า CSS ที่ต้องการ, JS บนหน้า
<link rel = "stylesheet" type = "text/css" href = "$ {pageContext.request.contextpath} /css/webuploader.css"> <script type = "text/javascript } /js/jQuery-1.10.2.min.js "> </script> <script type =" text/javascript "src =" $ {pageContext.request.contextpath} /js/webuploader.js "> </script>1.2 เขียนแท็กหน้าอัปโหลด
<!-อัปโหลด div-> <div id = "uploader"> <!-ข้อมูลรายการไฟล์แสดง-> <ul id = "filelist" ></ul> <!-เลือกพื้นที่ไฟล์-> <div id = "filepicker"> คลิกเพื่อเลือกไฟล์ </div> </div>
1.3 การเขียนโค้ด webpload
<script type = "text/javascript"> // 1 เริ่มต้น webPload และกำหนดค่าพารามิเตอร์ส่วนกลาง var uploader = webPloader.create ({// ที่อยู่ควบคุม Flashk swf: "$ {pageContext.request.contextpath} /js/uploader.swf" "#FilePicker", // อัปโหลดไฟล์อัตโนมัติอัตโนมัติ: จริง,}); // 2 หลังจากเลือกไฟล์แล้วการแสดงคิวข้อมูลไฟล์ // ลงทะเบียนเหตุการณ์ Filequeued: ทริกเกอร์เมื่อไฟล์ถูกเพิ่มลงในคิว // ไฟล์: แสดงถึงไฟล์ uploader.on ("filequeued", ฟังก์ชั่น (ไฟล์) {// เพิ่มข้อมูลไฟล์ div $ (#filelist ") class = 'fileinfo'> <pan> "+file.name+" </span> <div class = 'state'> กำลังรอการอัปโหลด ... </div> <span class = 'text'> </span> </div> ");}); // 3 ลงทะเบียนการอัปโหลดความคืบหน้าการฟัง // ไฟล์: การอัปโหลดไฟล์ // เปอร์เซ็นต์: สัดส่วนของความคืบหน้าปัจจุบัน สูงสุดคือ 1 ตัวอย่างเช่น: 0.2uploader.on ("UploadProgress", ฟังก์ชั่น (ไฟล์, เปอร์เซ็นต์) {var id = $ ("#"+file.id); // อัปเดตข้อมูลสถานะ id.find ("div.state") ข้อความ ("อัปโหลด ... "); id.find ("span.text"). text (math.round (เปอร์เซ็นต์*100)+"%");}); // 4 ลงทะเบียนและอัปโหลดการฟัง // ไฟล์: อัปโหลดไฟล์ // การตอบกลับ: ข้อมูลที่ส่งคืนโดยพื้นหลัง, return uploader.on ("uploadsuccess", ฟังก์ชั่น (ไฟล์, การตอบกลับ) {// อัปเดตข้อมูลสถานะ $ ("#"+file.id) .find ("div.state") ข้อความ ("อัปโหลด");};);2) รหัสเซิร์ฟเล็ตแบ็กเอนด์
DiskFileItemFactory Factory = ใหม่ diskFileItemFactory (); servletFileUpload SFU = ใหม่ servletFileUpload (โรงงาน); sfu.setheaderencoding ("utf-8"); ลอง {list <fileItem> รายการ = sfu.parserequest ข้อมูล} else {// ข้อมูลไฟล์ // ตัดสินว่าเฉพาะไฟล์ที่จำเป็นต้องได้รับการบันทึกและประมวลผล system.out.println ("ชื่อไฟล์ที่ได้รับ:"+item.getName ()); // คัดลอกไฟล์ไปยังฮาร์ดดิสก์ในไฟล์พื้นหลัง บันทึกได้สำเร็จ ");}}} catch (fileuploadexception e) {e.printstacktrace ();}สร้างภาพขนาดย่อภาพ
จุดสำคัญ: โทร Updoader.makethumb () วิธีการสร้างรูปขนาดย่อ
uploader.on ("filequeued", function (ไฟล์) {// ต่อไปข้อมูลไฟล์ div $ ("#filelist") ผนวก ("<div id = '" file.id+"' class = 'fileinfo'> <img/> <pan> class = 'text'> </span> </div> "); // ทำภาพย่อของภาพ: โทร makethumb () เมธอด // ข้อผิดพลาด: ล้มเหลวในการสร้างรูปขนาดย่อ // src: เส้นทางของ Thumbnails uploader.makethumb (ไฟล์, function (ข้อผิดพลาด, src) {var id = $ ("#" ถ้า (ข้อผิดพลาด) {id.find ("img"). replacewith ("ไม่สามารถดูตัวอย่าง");} // หากประสบความสำเร็จรูปขนาดย่อจะถูกแสดงไปยังตำแหน่งที่ระบุ id.find ("img"). attr ("src", src);ลากวางและอัปโหลด
1) เพิ่ม div ลงในพื้นที่ลากบนหน้า
<!-อัปโหลด div-> <div id = "uploader"> <!-พื้นที่การลากไฟล์-> <div id = "dndarea"> <p> ลากไฟล์โดยตรงที่นี่เพื่ออัปโหลดโดยอัตโนมัติ </p> </div> <!
2) เพิ่มพารามิเตอร์การลากและวางลงในพารามิเตอร์การกำหนดค่าส่วนกลางของ webPloader
// 1. เริ่มต้น webPload และกำหนดค่าพารามิเตอร์ส่วนกลาง var uploader = webPloader.create ({// ที่อยู่ควบคุม Flashk swf: "$ {pageContext.request.contextpath} /js/uploader.swf" เลือก: "#filepicker", // การอัปโหลดไฟล์อัตโนมัติอัตโนมัติ: จริง, // เปิดใช้งานฟังก์ชั่นการลากและวาง, ระบุพื้นที่ลาก dnd: "#dndarea", // ปิดใช้งานฟังก์ชั่นการลากและวางในสถานที่อื่น ๆ ของหน้าเพื่อป้องกันไม่ให้หน้าเปิดไฟล์ disableglobaldndอัปโหลดไฟล์ขนาดใหญ่เป็นชิ้น
1) เพิ่มพารามิเตอร์การอัปโหลดบล็อกไปยังพารามิเตอร์ส่วนกลางของ webPloader
// 1. เริ่มต้น webPload และกำหนดค่าพารามิเตอร์ส่วนกลาง var uploader = webPloader.create ({// ที่อยู่ควบคุม Flashk swf: "$ {pageContext.request.contextpath} /js/uploader.swf" เลือก: "#filepicker", // Auto Upload File Auto: จริง, // เปิดใช้งานฟังก์ชั่นการลากและวาง, ระบุพื้นที่ลาก dnd: "#dndarea", // ปิดใช้งานการลากและวางฟังก์ชั่นในสถานที่อื่นเพื่อป้องกันไม่ให้หน้าเปิดไฟล์ disableglobaldnd chunked: จริง, // ขนาดไฟล์ต่อบล็อก (เริ่มต้น 5m) chunksize: 5*1024*1024, // เปิดเธรดที่เกิดขึ้นพร้อมกันหลายรายการ (ค่าเริ่มต้น 3) เธรด: 3, // เมื่ออัปโหลดไฟล์ปัจจุบัน preperenextfile: true});2) ตรวจสอบจุดเวลาสามจุดสำหรับการอัปโหลดไฟล์
หลังจากเพิ่มการกำหนดค่าสามแบบข้างต้นคุณจะพบว่าเมื่อไฟล์เกิน 5 เมตร webploader จะส่งไฟล์ไปยังพื้นหลังโดยอัตโนมัติ
คำขอบล็อกแต่ละรายการมีข้อมูล:
คุณสามารถฟังจุดเวลาสำคัญสามจุดในการอัปโหลดไฟล์เป็นชิ้น
ก่อนส่งไฟล์: โทรก่อนส่งก่อนส่งมอบ: หากมีบล็อกให้โทรติดต่อหลังส่งไฟล์ก่อนแต่ละบล็อกจะถูกส่ง: เรียกหลังจากบล็อกทั้งหมดจะถูกส่ง // 5 ตรวจสอบจุดเวลาสามจุดของการอัปโหลดไฟล์ (หมายเหตุ: ส่วนของรหัสนี้จะต้องวางไว้ก่อนที่ webploader.create) // เวลาเวลา 1 :: ก่อนที่บล็อกทั้งหมดจะถูกอัปโหลด (1. เครื่องหมายที่ไม่ซ้ำกันของไฟล์สามารถคำนวณได้หรือไม่ เบรกพอยต์การส่งอย่างต่อเนื่อง) // ขั้นตอนที่ 3: หลังจากอัปโหลดชิ้นทั้งหมดได้สำเร็จ (1. แจ้งพื้นหลังของไฟล์ก้อนเพื่อผสาน) webuploader.uploader.register ({"ก่อนส่งไฟล์": "beforesendfile" ก่อนหน้านี้ "ก่อนหน้านี้" ชิ้นส่วนทั้งหมด beforesendfi le: function () {// 1 ร้องขอว่าพื้นหลังได้บันทึกบล็อกปัจจุบันหรือไม่ หากมีอยู่ให้ข้ามไฟล์บล็อกเพื่อรับรู้ฟังก์ชั่นการส่งอย่างต่อเนื่องของเบรกพอยต์}, // ขั้นตอนที่ 3: เรียกใช้ฟังก์ชั่นนี้หลังจากที่บล็อกทั้งหมดได้รับการอัปโหลดสำเร็จ AftersEndFile: function () {// 1 หากอัปโหลดเป็นบล็อกไฟล์บล็อกทั้งหมดจะถูกรวมเข้าด้วยกันผ่านพื้นหลัง}});ตรรกะก่อนส่งไฟล์:
// ใช้เมธอด md5file () เพื่อคำนวณแท็กที่ไม่ซ้ำกันของไฟล์ // ฟังก์ชั่นนี้ได้รับ deverredbeforesendfile: ฟังก์ชั่น (ไฟล์) {// สร้าง deferredvar deverred = webuploader.deferred (); // 1 คำนวณแท็กที่ไม่ซ้ำกันของไฟล์ที่ใช้สำหรับการส่งอย่างต่อเนื่องและการส่งสัญญาณที่สอง (ใหม่ webploader.uploader ()). md5file (ไฟล์, 0,5*1024*1024) .progress (ฟังก์ชั่น (เปอร์เซ็นต์) {$ ("#" สืบค้น ... ");}) จากนั้น (ฟังก์ชั่น (val) {uniqueFileTag = val; $ ("#"+file.id) .find (" div.state ") ข้อความ (" ข้อมูลไฟล์ที่ได้รับสำเร็จ "); // เฉพาะเมื่อข้อมูลไฟล์ได้สำเร็จ ร้องขอว่าพื้นหลังได้บันทึกไฟล์หรือไม่ หากมีอยู่ไฟล์จะถูกข้ามเพื่อรับรู้ฟังก์ชั่นการส่งผ่านครั้งที่สอง // return deverred.promise ();}ตรรกะก่อนส่ง:
// ส่งแท็กที่ไม่ซ้ำกันของไฟล์ปัจจุบันไปยังพื้นหลังซึ่งใช้เพื่อสร้างไดเรกทอรีที่บันทึกไฟล์ chunked beforesend: function () {// พกพาแท็กที่ไม่ซ้ำกันของไฟล์ปัจจุบันไปยังพื้นหลังซึ่งใช้เพื่อสร้างไดเรกทอรีที่บันทึกไฟล์ chunked this.owner.options3) พื้นหลังจำเป็นต้องบันทึกไฟล์ chunked ทั้งหมด
// สร้างไดเรกทอรีสำหรับแต่ละไฟล์และบันทึกไฟล์ chunked ทั้งหมดของไฟล์นี้ // ตัดสินว่ามันได้รับการอัปโหลดเป็นชิ้นถ้า (chunks! = null) {system.out.println ("การประมวลผลก้อน ... "); // สร้างไดเรกทอรีชั่วคราว if (! chunksdir.exists ()) {chunksdir.mkdir ();} ถ้า (chunk! = null) {// บันทึก chunkfile chunkfile = ไฟล์ใหม่ (chunksdir.getpath ()+"/" chunk)4) แผนกต้อนรับแจ้งให้แบ็กเอนด์รวมไฟล์ chunked ทั้งหมด
// แผนกต้อนรับจะแจ้งให้พื้นหลังผสานไฟล์ลอจิกไฟล์หลังจบไฟล์: aftersendFile: ฟังก์ชั่น (ไฟล์) {// 1 หากอัปโหลดเป็นชิ้นให้ผสานไฟล์ก้อนทั้งหมดผ่านพื้นหลัง // ขอพื้นหลังเพื่อผสานไฟล์ $ .ajax ({ประเภท: "โพสต์", url: "$ {pageContext.request.contextpath}/uploadCheckServlet? FileName: file.name}, datatype: "json", ความสำเร็จ: ฟังก์ชั่น (การตอบสนอง) {alert (response.msg);}});} // พื้นหลังรวมไฟล์ chunked ทั้งหมดถ้า ("mergechunks" .equals request.getParameter ("filemd5"); String filename = request.getParameter ("filename"); // อ่านไฟล์ทั้งหมดในไฟล์ไดเรกทอรี f = ไฟล์ใหม่ (ServerPath+"/"+filemd5); ไฟล์ [] filearray = f.listfiles {ถ้า (pathName.isDirectory ()) {return false;} return true;}}); // แปลงเป็นคอลเลกชันเพื่ออำนวยความสะดวกในการเรียงลำดับรายการ <file> fileList = new ArrayList <File> (array.aslist (filearray)); {if (integer.parseint (o1.getName ())) <integer.parseint (o2.getName ())) {return -1;} return 1;}}); file outputfile = ไฟล์ใหม่ (ServerPath+"/"+filename); fileOutputStream (outputFile) .getChannel (); // ผสาน FileChannel inchannel; สำหรับ (ไฟล์ไฟล์: fileList) {inChannel = ใหม่ fileInputStream (ไฟล์) .getChannel (); inchannel.transferto (0, inchannel.size (), outchannel); inchannel.close (); if (tempfile.isdirectory () && tempfile.exists ()) {tempfile.delete ();} // ปิดสตรีม outchannel.close (); response.setContentType ("ข้อความ/html; charset = utf-8"); ประสบความสำเร็จ/"}");}จุดพักไฟล์ขนาดใหญ่ยังคงดำเนินต่อไป
ขึ้นอยู่กับการใช้งานการอัพโหลดบล็อกมันเป็นเรื่องง่ายมากที่จะใช้การส่งสัญญาณเบรกพอยต์อย่างต่อเนื่อง! - -
ส่วนหน้า:
// เวลาที่ 2: หากมีการอัปโหลดบล็อกฟังก์ชั่นนี้เรียกก่อนการอัปโหลดแต่ละบล็อก // บล็อก: แสดงถึงวัตถุบล็อกปัจจุบันก่อนหน้านี้: ฟังก์ชั่น (บล็อก) {// 1 ร้องขอว่าพื้นหลังได้บันทึกบล็อกปัจจุบันหรือไม่ หากมีอยู่ให้ข้ามไฟล์บล็อกเพื่อรับรู้ฟังก์ชั่นการส่งอย่างต่อเนื่องของเบรกพอยต์ var deferred = webploader.deverred (); // ร้องขอว่าพื้นหลังจะบันทึกข้อมูลไฟล์หรือไม่ หากได้รับการบันทึกมันจะถูกข้ามไป หากไม่มีเนื้อหาก้อนจะถูกส่ง $ .ajax ({type: "post", url: "$ {pageContext.request.contextpath}/uploadcheckservlet? action = checkChunk" ข้อมูล: {// ไฟล์ที่ไม่ซ้ำกัน lock.end-block.start}, ประเภทข้อมูล: "json", ความสำเร็จ: ฟังก์ชั่น (การตอบสนอง) {ถ้า (response.ifexist) {// บล็อกมีอยู่, ข้ามบล็อก deverred.reject ();} else {// บล็อกไม่มีอยู่ พื้นหลังสร้างไดเรกทอรีที่บันทึกบล็อกไฟล์ this.owner.options.formdata.filemd5 = filemd5; return deverred.promise (); -หลังเวที:
// ตรวจสอบว่าก้อนมีอยู่หรือบันทึกโมฆะส่วนตัว CheckChunk (คำขอ httpservletrequest, httpservletResponse การตอบสนอง) พ่น IOException, filenotFoundException {system.out.println ("CheckChunk ... "); string FileMd5 = คำขอ request.getParameter ("chunksize"); file checkfile = ไฟล์ใหม่ (ServerPath+"/"+filemd5+"/"+chunk); response.setContContentType ("ข้อความ/html; charset = utf-8"); checkfile.length () == integer.parseint (chunksize)) {response.getWriter () เขียน ("{/" ifexist/": 1}");} else {response.getWriter () เขียน ("/" ifexist/": 0}");การถ่ายโอนไฟล์ในไม่กี่วินาที
ก่อนการร้องขอบล็อกทั้งหมดฟังก์ชันการถ่ายโอนครั้งที่สองสามารถนำไปใช้ได้! - -
ส่วนหน้า:
BEFORESENDFILE: ฟังก์ชั่น (ไฟล์) {// สร้าง defferedVar deferred = webPloader.deverred (); // 1 คำนวณเครื่องหมายที่ไม่ซ้ำกันของไฟล์ที่ใช้สำหรับการส่งสัญญาณอย่างต่อเนื่องและการส่งครั้งที่สอง (ใหม่ webploader.uploader ()). md5file (ไฟล์, 0,5*1024*1024) .progress (ฟังก์ชั่น (เปอร์เซ็นต์) {$ ("#" ไฟล์. val; $ ("#"+file.id) .find ("Div.State") ข้อความ ("ข้อมูลไฟล์ที่ได้รับสำเร็จ"); // 2 $ .ajax ({type: "post", url: "$ {pageContext.request.contextpath}/uploadcheckservlet? action = fileCheck", ข้อมูล: {// แท็กที่ไม่ซ้ำกันของไฟล์ filemd5: filemd5}, datatype: "json", ความสำเร็จ: ฟังก์ชั่น (การตอบสนอง) {ถ้า (response.ifexist) {$ ("#"+file.id). Find ("div.state") ข้อความ ("ประสบความสำเร็จ deferred.resolve ();}}});}); // return deferreturn deverred.promise ();},},หลังเวที:
// ตรวจสอบว่าข้อมูล MD5 ของไฟล์เกี่ยวข้องกับฐานข้อมูลโมฆะส่วนตัว FileCheck (คำขอ httpservletRequest, การตอบสนอง httpservletResponse) พ่น IOException, filenotFoundException {String filemd5 = request.getParameter ("filemd5"); hashmap <string, string> (); database.put ("576018603f4091782b68b78af85704a1", "01. หลักสูตรหลักสูตร Review.itcast "); Response.setContentType (" ข้อความ/html; charset = utf-8 "); ถ้า (database.containskey (filemd5)) {response.getWriter () เขียน (" {/"ifexist/": 1} ");ข้างต้นเป็นตัวอย่างคำอธิบายของการอัปโหลดไฟล์ Javaweb และดาวน์โหลดที่ตัวแก้ไขแนะนำให้คุณ (เทคโนโลยีการอัปโหลดไฟล์เย็น) ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับทุกคนในเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!