2012-02-09 14 views
38

पर एक पीएनजी छवि कैसे वापस करें मेरे पास जर्सी आरईएसटी संसाधनों के साथ एक वेब सर्वर चल रहा है और मुझे आश्चर्य है कि ब्राउज़र आईएमजी टैग के लिए छवि/पीएनजी संदर्भ कैसे प्राप्त करें; एक फॉर्म जमा करने या अजाक्स प्रतिक्रिया प्राप्त करने के बाद। ग्राफिक्स जोड़ने के लिए छवि प्रसंस्करण कोड काम कर रहा है, बस इसे किसी भी तरह वापस करने की जरूरत है।जर्सी आरईएसटी सेवा विधि से ब्राउजर

कोड:

@POST 
@Path("{fullsize}") 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
@Produces("image/png") 
// Would need to replace void 
public void getFullImage(@FormDataParam("photo") InputStream imageIS, 
         @FormDataParam("submit") String extra) { 

     BufferedImage image = ImageIO.read(imageIS); 

     // .... image processing 
     //.... image processing 

     return ImageIO. .. ? 

} 

चीयर्स

+0

आप पूरा करने के लिए कोशिश कर रहे हैं? क्या आप छवि के स्थान के साथ यूआरआई भेजकर इसे प्राप्त नहीं कर सकते? – Perception

+0

मैं चाहता हूं कि उपयोगकर्ता कुछ ऑर्डर देने से पहले फोटो पर चयनित ग्राफिक्स का पूर्वावलोकन करे। अब मैं देखता हूं कि यह AJAX पोस्ट के साथ नहीं किया जा सकता है, जैसा कि आपने संसाधित छवि को इंगित करते हुए वेब पृष्ठों का अनुरोध करने की आवश्यकता होगी। – gorn

उत्तर

79

मैं अपनी एक अच्छा विचार आश्वस्त नहीं कर रहा हूँ एक बाकी सेवा में छवि डेटा वापस जाने के लिए। यह आपके एप्लिकेशन सर्वर की मेमोरी और आईओ बैंडविड्थ से जुड़ा हुआ है। उस कार्य को उचित वेब सर्वर पर सौंपने के लिए बहुत बेहतर है जिसे इस तरह के स्थानांतरण के लिए अनुकूलित किया गया है। आप छवि संसाधन पर रीडायरेक्ट भेजकर इसे पूरा कर सकते हैं (छवि के यूआरआई के साथ HTTP 302 प्रतिक्रिया के रूप में)। यह निश्चित रूप से मानता है कि आपकी छवियों को वेब सामग्री के रूप में व्यवस्थित किया गया है।

कहा करने के बाद कि, यदि आप क्या तुम सच में तय एक वेब सेवा से छवि डेटा स्थानांतरित करने की जरूरत है तो आप निम्न (छद्म) कोड के साथ ऐसा कर सकते हैं:

@Path("/whatever") 
@Produces("image/png") 
public Response getFullImage(...) { 

    BufferedImage image = ...; 

    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ImageIO.write(image, "png", baos); 
    byte[] imageData = baos.toByteArray(); 

    // uncomment line below to send non-streamed 
    // return Response.ok(imageData).build(); 

    // uncomment line below to send streamed 
    // return Response.ok(new ByteArrayInputStream(imageData)).build(); 
} 

अपवाद हैंडलिंग में जोड़ें, वगैरह वगैरह

+0

धन्यवाद! यह करने का एक तरीका है। – gorn

+0

एक PHP सर्वर अनुप्रयोग है कि cURL इस्तेमाल किया यह RESTful जावा वेब सेवा से चित्र प्राप्त करने और HTML छवि टैग में उन्हें बताया साथ समाप्त हो गया। – gorn

+0

@gorn आप पहले – kommradHomer

11

मैं निम्न सुविधाओं के साथ उस के लिए एक सामान्य विधि का निर्माण:

  • को वापस लौटाती "संशोधित नहीं" अगर फ़ाइल स्थानीय रूप से संशोधित नहीं किया गया, एक Status.NOT_MODIFIED फोन करने वाले को भेजा जाता है। Apache Commons Lang
  • का उपयोग करता है यहाँ कोड एक फ़ाइल धारा वस्तु का उपयोग कर के बजाय फ़ाइल स्वयं

पढ़ने:

import org.apache.commons.lang3.time.DateUtils; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

private static final Logger logger = LoggerFactory.getLogger(Utils.class); 

@GET 
@Path("16x16") 
@Produces("image/png") 
public Response get16x16PNG(@HeaderParam("If-Modified-Since") String modified) { 
    File repositoryFile = new File("c:/temp/myfile.png"); 
    return returnFile(repositoryFile, modified); 
} 

/** 
* 
* Sends the file if modified and "not modified" if not modified 
* future work may put each file with a unique id in a separate folder in tomcat 
* * use that static URL for each file 
* * if file is modified, URL of file changes 
* * -> client always fetches correct file 
* 
*  method header for calling method public Response getXY(@HeaderParam("If-Modified-Since") String modified) { 
* 
* @param file to send 
* @param modified - HeaderField "If-Modified-Since" - may be "null" 
* @return Response to be sent to the client 
*/ 
public static Response returnFile(File file, String modified) { 
    if (!file.exists()) { 
     return Response.status(Status.NOT_FOUND).build(); 
    } 

    // do we really need to send the file or can send "not modified"? 
    if (modified != null) { 
     Date modifiedDate = null; 

     // we have to switch the locale to ENGLISH as parseDate parses in the default locale 
     Locale old = Locale.getDefault(); 
     Locale.setDefault(Locale.ENGLISH); 
     try { 
      modifiedDate = DateUtils.parseDate(modified, org.apache.http.impl.cookie.DateUtils.DEFAULT_PATTERNS); 
     } catch (ParseException e) { 
      logger.error(e.getMessage(), e); 
     } 
     Locale.setDefault(old); 

     if (modifiedDate != null) { 
      // modifiedDate does not carry milliseconds, but fileDate does 
      // therefore we have to do a range-based comparison 
      // 1000 milliseconds = 1 second 
      if (file.lastModified()-modifiedDate.getTime() < DateUtils.MILLIS_PER_SECOND) { 
       return Response.status(Status.NOT_MODIFIED).build(); 
      } 
     } 
    }   
    // we really need to send the file 

    try { 
     Date fileDate = new Date(file.lastModified()); 
     return Response.ok(new FileInputStream(file)).lastModified(fileDate).build(); 
    } catch (FileNotFoundException e) { 
     return Response.status(Status.NOT_FOUND).build(); 
    } 
} 

/*** copied from org.apache.http.impl.cookie.DateUtils, Apache 2.0 License ***/ 

/** 
* Date format pattern used to parse HTTP date headers in RFC 1123 format. 
*/ 
public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; 

/** 
* Date format pattern used to parse HTTP date headers in RFC 1036 format. 
*/ 
public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz"; 

/** 
* Date format pattern used to parse HTTP date headers in ANSI C 
* <code>asctime()</code> format. 
*/ 
public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy"; 

public static final String[] DEFAULT_PATTERNS = new String[] { 
    PATTERN_RFC1036, 
    PATTERN_RFC1123, 
    PATTERN_ASCTIME 
}; 

ध्यान दें कि लोकेल स्विचिंग धागे की सुरक्षा के लिए प्रतीत नहीं होता। मुझे लगता है, वैश्विक स्तर पर लोकेल को स्विच करना बेहतर है। मैं साइड इफेक्ट्स के बारे में निश्चित नहीं हूं ...

+3

आप, जर्सी के Request.evaluatePreconditions (...) का उपयोग करके अपने अंतिम संशोधित तर्क का एक बहुत निकालना चाहिए, अन्यथा पार्स करने और जाँच तारीखों संभाल लेंगे, और etags अगर आप उन्हें समर्थन कर सकते हैं। – bramp

6

@ पेरिसप्शन से उत्तर के संबंध में, बाइट एरे के साथ काम करते समय बहुत मेमोरी लेने वाला यह सच है, लेकिन आप आउटपुटस्ट्रीम

में भी वापस लिख सकते हैं
@Path("/picture") 
public class ProfilePicture { 
    @GET 
    @Path("/thumbnail") 
    @Produces("image/png") 
    public StreamingOutput getThumbNail() { 
    return new StreamingOutput() { 
     @Override 
     public void write(OutputStream os) throws IOException, WebApplicationException { 
     //... read your stream and write into os 
     } 
    }; 
    } 
} 
3

आप छवि संसाधन के तरीकों की एक संख्या है, तो यह अच्छी तरह से उत्पादन करने के लिए एक MessageBodyWriter BufferedImage बनाने के लायक है:

@Produces({ "image/png", "image/jpg" }) 
@Provider 
public class BufferedImageBodyWriter implements MessageBodyWriter<BufferedImage> { 
    @Override 
    public boolean isWriteable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) { 
    return type == BufferedImage.class; 
    } 

    @Override 
    public long getSize(BufferedImage t, Class<?> type, Type type1, Annotation[] antns, MediaType mt) { 
    return -1; // not used in JAX-RS 2 
    } 

    @Override 
    public void writeTo(BufferedImage image, Class<?> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, Object> mm, OutputStream out) throws IOException, WebApplicationException { 
    ImageIO.write(image, mt.getSubtype(), out); 
    } 
} 

यह MessageBodyWriter स्वचालित रूप से उपयोग किया जाएगा यदि स्वत: खोज जर्सी के लिए सक्षम है, अन्यथा इसे फिर से शुरू करने की जरूरत है एक कस्टम अनुप्रयोग उप-वर्ग द्वारा ned। अधिक जानकारी के लिए JAX-RS Entity Providers देखें।

एक बार यह सेट किया गया है, बस एक संसाधन विधि से एक BufferedImage लौट सकते हैं और यह छवि फ़ाइल डेटा के रूप में उत्पादन होना होगा:

इस दृष्टिकोण के लिए लाभ के एक जोड़े:

  • यह प्रतिक्रिया मध्यस्थ BufferedOutputStream
  • के बजाय प्रतिक्रिया आउटपुटस्टेम को लिखता है यह पीएनजी और जेपीजी आउटपुट (संसाधन विधि द्वारा अनुमत मीडिया प्रकारों के आधार पर) दोनों का समर्थन करता है
संबंधित मुद्दे