ทำไมภาพของฉันจึงออกมาเป็นรอยขีดข่วน?
หากคุณเป็นนักพัฒนา Java ที่ใช้เซิร์ฟเลตและการอัปโหลดไฟล์ คุณอาจพบปัญหาที่น่าหงุดหงิด: ภาพที่อัปโหลดที่ปรากฏว่าเป็นรอยขีดข่วนหรือเสียหายเมื่อเปิด นี่อาจทำให้สับสน โดยเฉพาะอย่างยิ่งถ้าไฟล์ข้อความอัปโหลดได้โดยไม่มีปัญหา ในบล็อกโพสต์นี้ เราจะสำรวจว่าเหตุใดสิ่งนี้จึงเกิดขึ้นและให้คำแนะนำที่ชัดเจนเพื่อแก้ไขปัญหา
การทำความเข้าใจกับปัญหา
เมื่อทำงานกับการอัปโหลดไฟล์ โดยเฉพาะอย่างยิ่งไฟล์ภาพ สิ่งสำคัญคือต้องจัดการกับข้อมูลแบบไบนารีอย่างถูกต้อง ผลลัพธ์ที่ถูกรบกวนมักบ่งบอกว่าการอ่านข้อมูลไบนารีไม่ได้ทำอย่างถูกต้องหรือไม่เขียนไปยังไฟล์อย่างถูกต้อง โค้ดส่วนล่างนี้แสดงถึงวิธีการอัปโหลดไฟล์ทั่วไปโดยใช้ Apache Commons FileUpload:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
BufferedInputStream stream = new BufferedInputStream(item.openStream());
...
}
ในวิธีนี้ ภาพและไฟล์ไบนารีอื่น ๆ จะได้รับการประมวลผล แต่ลักษณะการอ่านข้อมูลอาจนำไปสู่ปัญหาที่ทำให้ไฟล์ภาพเสียหาย
การวิเคราะห์โค้ด
ส่วนสำคัญในโค้ดที่มีส่วนทำให้เกิดปัญหานั้นอยู่ภายในวิธีการอ่านไบต์จากสตรีมขาเข้า นี่คือโค้ดส่วนที่เกี่ยวข้อง:
public static byte[] getBytes(InputStream src, int buffsize) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buff = new byte[buffsize];
while (true) {
int nBytesRead = src.read(buff);
if (nBytesRead < 0) {
break;
}
byteStream.write(buff);
}
...
}
การระบุปัญหา
- การเขียนทั้งบัฟเฟอร์: บรรทัด
byteStream.write(buff);
เขียนข้อมูลทั้งบัฟเฟอร์โดยไม่คำนึงว่ามีการอ่านไปกี่ไบต์จริง ๆ ซึ่งเป็นปัญหา เนื่องจากในหลายกรณีnBytesRead
จะน้อยกว่าขนาดบัฟเฟอร์ ซึ่งหมายความว่าข้อมูลที่เหลือจากการอ่านก่อนหน้านี้อาจถูกเขียนไปยังออกพุต ทำให้เกิดความเสียหาย
วิธีแก้ปัญหาที่แนะนำ
เพื่อแก้ไขปัญหานี้ เราจำเป็นต้องปรับวิธีการเขียนไบต์ไปยัง ByteArrayOutputStream
โค้ดที่แก้ไขควรมีลักษณะดังนี้:
public static byte[] getBytes(InputStream src, int buffsize) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buff = new byte[buffsize];
while (true) {
int nBytesRead = src.read(buff);
if (nBytesRead < 0) {
break;
} else {
byteStream.write(buff, 0, nBytesRead); // เขียนเฉพาะไบต์ที่อ่าน
}
}
...
}
การเปลี่ยนแปลงที่สำคัญ
- การเขียนแบบมีเงื่อนไข: เงื่อนไข
else
ช่วยให้เราสามารถเขียนเฉพาะไบต์ที่ถูกอ่านจริงๆ - ความยาวที่ระบุ: เมื่อเขียน เราจะต้องระบุจำนวนไบต์ที่จะเขียน โดยใช้
byteStream.write(buff, 0, nBytesRead);
การเปลี่ยนแปลงเหล่านี้ช่วยป้องกันไม่ให้ข้อมูลที่เก่าและไม่จำเป็นถูกเขียนไป และทำให้แน่ใจว่าไฟล์ภาพได้รับการเก็บรักษาโดยไม่มีการเสียหาย
สรุป
หากคุณประสบปัญหากับการอัปโหลดภาพในแอปพลิเคชัน Java ของคุณ สาเหตุส่วนใหญ่มักจะอยู่ที่วิธีที่คุณจัดการกับสตรีมขาเข้า ด้วยการปรับปรุงตรรกะการอ่านและเขียนสตรีมไบต์ของคุณ คุณสามารถกำจัดปัญหาที่นำไปสู่ภาพที่ถูกรบกวนได้
ด้วยการปฏิบัติตามแนวทางข้างต้นและแก้ไขวิธีการอ่านและเขียนสตรีมไบต์ คุณสามารถป้องกันปัญหาในอนาคตเกี่ยวกับการอัปโหลดไฟล์ในแอปพลิเคชัน Java ของคุณ ขอให้สนุกกับการเขียนโค้ด!