ทำไมภาพของฉันจึงออกมาเป็นรอยขีดข่วน?

หากคุณเป็นนักพัฒนา 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); // เขียนเฉพาะไบต์ที่อ่าน
        }
    }
    ...
}

การเปลี่ยนแปลงที่สำคัญ

  1. การเขียนแบบมีเงื่อนไข: เงื่อนไข else ช่วยให้เราสามารถเขียนเฉพาะไบต์ที่ถูกอ่านจริงๆ
  2. ความยาวที่ระบุ: เมื่อเขียน เราจะต้องระบุจำนวนไบต์ที่จะเขียน โดยใช้ byteStream.write(buff, 0, nBytesRead);

การเปลี่ยนแปลงเหล่านี้ช่วยป้องกันไม่ให้ข้อมูลที่เก่าและไม่จำเป็นถูกเขียนไป และทำให้แน่ใจว่าไฟล์ภาพได้รับการเก็บรักษาโดยไม่มีการเสียหาย

สรุป

หากคุณประสบปัญหากับการอัปโหลดภาพในแอปพลิเคชัน Java ของคุณ สาเหตุส่วนใหญ่มักจะอยู่ที่วิธีที่คุณจัดการกับสตรีมขาเข้า ด้วยการปรับปรุงตรรกะการอ่านและเขียนสตรีมไบต์ของคุณ คุณสามารถกำจัดปัญหาที่นำไปสู่ภาพที่ถูกรบกวนได้


ด้วยการปฏิบัติตามแนวทางข้างต้นและแก้ไขวิธีการอ่านและเขียนสตรีมไบต์ คุณสามารถป้องกันปัญหาในอนาคตเกี่ยวกับการอัปโหลดไฟล์ในแอปพลิเคชัน Java ของคุณ ขอให้สนุกกับการเขียนโค้ด!