2010-11-12 33 views
22

Trong ứng dụng web của tôi, tôi có mô-đun tải lên hình ảnh. Tôi muốn kiểm tra tệp đã tải lên cho dù đó là tệp hình ảnh hay bất kỳ tệp nào khác. Tôi đang sử dụng Java ở phía máy chủ.Cách kiểm tra tệp đã tải lên cho dù đó là hình ảnh hay tệp khác?

Những hình ảnh được đọc như BufferedImage trong java và sau đó tôi viết nó vào đĩa với ImageIO.write()

Làm thế nào tôi có trách nhiệm kiểm tra BufferedImage, cho dù đó là thực sự là một hình ảnh hay cái gì khác?

Mọi đề xuất hoặc liên kết sẽ được đánh giá cao.

+0

Tốt nhất là nhìn vào phần mở rộng tập tin, không có phương pháp 100% để xác định xem một tập tin là một hình ảnh hay không. –

Trả lời

85

Tôi giả định rằng bạn đang chạy điều này trong ngữ cảnh servlet. Nếu đó là giá cả phải chăng để kiểm tra loại nội dung dựa trên phần mở rộng tệp, sau đó sử dụng ServletContext#getMimeType() để nhận loại mime (loại nội dung). Chỉ cần kiểm tra xem nó có bắt đầu bằng image/ hay không.

String fileName = uploadedFile.getFileName(); 
String mimeType = getServletContext().getMimeType(fileName); 
if (mimeType.startsWith("image/")) { 
    // It's an image. 
} 

Loại mime mặc định được xác định trong web.xml của servletcontainer được đề cập. Ví dụ Tomcat, nó nằm ở /conf/web.xml. Bạn có thể mở rộng/ghi đè lên nó trong /WEB-INF/web.xml của webapp của bạn như sau:

<mime-mapping> 
    <extension>svg</extension> 
    <mime-type>image/svg+xml</mime-type> 
</mime-mapping> 

Nhưng điều này không ngăn cản bạn từ những người dùng đang lừa dối bạn bằng cách thay đổi phần mở rộng tập tin. Nếu bạn muốn bao gồm điều này, bạn cũng có thể xác định loại mime dựa trên nội dung tệp thực tế. Nếu nó là giá cả phải chăng để kiểm tra chỉ BMP, GIF, JPG hoặc PNG loại (nhưng không TIF, PSD, SVG, vv), sau đó bạn chỉ có thể ăn nó trực tiếp đến ImageIO#read() và kiểm tra xem nó không ném một ngoại lệ.

try (InputStream input = uploadedFile.getInputStream()) { 
    try { 
     ImageIO.read(input).toString(); 
     // It's an image (only BMP, GIF, JPG and PNG are recognized). 
    } catch (Exception e) { 
     // It's not an image. 
    } 
} 

Nhưng nếu bạn muốn để trang trải nhiều loại hình ảnh là tốt, sau đó xem xét sử dụng một thư viện của bên thứ 3 mà làm tất cả công việc bằng cách can thiệp các file headers. Ví dụ: JMimeMagic hoặc Apache Tika hỗ trợ cả BMP, GIF, JPG, PNG, TIF và PSD (nhưng không phải SVG). Apache Batik hỗ trợ SVG. Ví dụ dưới đây sử dụng JMimeMagic:

try (InputStream input = uploadedFile.getInputStream()) { 
    String mimeType = Magic.getMagicMatch(input, false).getMimeType(); 
    if (mimeType.startsWith("image/")) { 
     // It's an image. 
    } else { 
     // It's not an image. 
    } 
} 

Bạn có thể nếu cần sử dụng kết hợp và lớn hơn cái kia và khác.

Điều đó nói rằng, bạn không nhất thiết cần ImageIO#write() để lưu hình ảnh được tải lên đĩa. Chỉ cần viết được InputStream trực tiếp đến một Path hoặc bất kỳ OutputStream như FileOutputStream Java IO theo cách thông thường là đầy đủ hơn (xem thêm Recommended way to save uploaded files in a servlet application):

try (InputStream input = uploadedFile.getInputStream()) { 
    Files.copy(input, new File(uploadFolder, fileName).toPath()); 
} 

Trừ khi bạn muốn thu thập một số thông tin hình ảnh như kích thước của nó và/hoặc muốn thao tác nó (crop/resize/rotate/convert/etc) tất nhiên.

+2

Câu trả lời rất toàn diện, bao gồm tất cả các khía cạnh. Làm tốt lắm ... – Cahit

+0

Tôi đã thử ImageIO.read (đầu vào); nhưng nó không ném bất kỳ ngoại lệ nào khi tệp không phải là hình ảnh. –

+3

ImageIO.read (đầu vào); không ném bất kỳ ngoại lệ nào nếu tệp không phải là hình ảnh, thay vào đó nó chỉ trả về giá trị rỗng. –

2

Tôi đã sử dụng org.apache.commons.imaging.Imaging trong trường hợp của mình. Dưới đây là một đoạn mã mẫu để kiểm tra xem hình ảnh có phải là hình ảnh jpeg hay không. Nó ném ImageReadException nếu tập tin được tải lên không phải là một hình ảnh.

try { 
     //image is InputStream 
     byte[] byteArray = IOUtils.toByteArray(image); 
     ImageFormat mimeType = Imaging.guessFormat(byteArray); 
     if (mimeType == ImageFormats.JPEG) { 
      return; 
     } else { 
      // handle image of different format. Ex: PNG 
     } 
    } catch (ImageReadException e) { 
     //not an image 
    } 
+1

Tuy nhiên - tính đến tháng 6 năm 2017, lib không có phiên bản ổn định và chỉ chụp nhanh. Có thể nguy hiểm khi sử dụng trong sản phẩm – George

1

này được xây dựng vào JDK và chỉ đơn giản đòi hỏi một dòng với sự hỗ trợ cho

byte[] data = ; 
InputStream is = new BufferedInputStream(new ByteArrayInputStream(data)); 
String mimeType = URLConnection.guessContentTypeFromStream(is); 
//...close stream 
Các vấn đề liên quan