I'm developing an application with jquerymobile and Spring MVC. I'm getting an image in a controller as Inputstream and the next step is to pass this image to Javascript for show in a dialog with JqueryMobile.
How can I pass this java Inpustream image to javascript?
PS. The controller is called throught jquerymobile ajax so i have onSuccess method waiting to make something with returned data from controller.
Why not load that image from java using Jquery on a div?
var url = 'myimage.com/image_java_url?'+dataToSend
$('#myDiv').load(url, function(response, status, xhr) {
if (status = "success"){
$('#myDiv').html(response);
}
});
I assume you are creating a REST-endpoint to recieve an image. If so, you could make your Spring-endpoint take HttpServletResponse as an argument and stream the image out to the servlet outputstream.
Wrap the inputstream in a BufferedInputStream for to let it handle the buffering for you.
To get hold of the HttpServletResponse just add it as an argument to your method,
#RequestMapping(value = "/something")
public void helloWorld(HttpServletResponse response) {
InputStream imageStream = .....;
OutputStream oSteam = response.getOutputStream();
InputStream stream = new BufferedInputStream(imageStream );
int b = -1;
while((b = stream.read())> -1){
oSteam.write(b);
}
I haven't had much experience with Spring, but I would use the javax.ws.rs.core.Reponse class in Java EE. This will allow you to construct a http response using Response.ResponseBuilder, wrapping your InputStream.
i.e.
Response.ok(inputStream, MEDIA_TYPE.APPLICATION_OCTET_STREAM).build();
Related
In a Java (only) Play 2.3 project we need to send a non-chunked response of an InputStream directly to the client. The InputStream comes from a remote service from which we want to stream directly to the client, without blocking or buffering to a local file. Since we know the size before reading the input stream, we do not want a chunked response.
What is the best way to return a result for an input stream with a known size? (preferable without using Scala).
When looking at the default ok(file, ..) method for returning File objects it goes deep into play internals which are only accessible from scala, and it uses the play-internal execution context which can't even be accessed from outside. Would be nice if it would work identical, just with an InputStream.
FWIW I have now found a way to serve an InputStream, which basically duplicates the logic which the Results.ok(File) method to allow directly passing in an InputStream.
The key is to use the scala call to create an Enumerator from an InputStream: play.api.libs.iteratee.Enumerator$.MODULE$.fromStream
private final MessageDispatcher fileServeContext = Akka.system().dispatchers().lookup("file-serve-context");
protected void serveInputStream(InputStream inputStream, String fileName, long contentLength) {
response().setHeader(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileName + "\"");
// Set Content-Type header based on file extension.
scala.Option<String> contentType = MimeTypes.forFileName(fileName);
if (contentType.isDefined()) {
response().setHeader(CONTENT_TYPE, contentType.get());
} else {
response().setHeader(CONTENT_TYPE, ContentType.DEFAULT_BINARY.getMimeType());
}
response().setHeader(CONTENT_LENGTH, Long.toString(contentLength));
return new WrappedScalaResult(new play.api.mvc.Result(
new ResponseHeader(StatusCode.OK, toScalaMap(response().getHeaders())),
// Enumerator.fromStream() will also close the input stream once it is done.
play.api.libs.iteratee.Enumerator$.MODULE$.fromStream(
inputStream,
FILE_SERVE_CHUNK_SIZE,
fileServeContext),
play.api.mvc.HttpConnection.KeepAlive()));
}
/**
* A simple Result which wraps a scala result so we can call it from our java controllers.
*/
private static class WrappedScalaResult implements Result {
private play.api.mvc.Result scalaResult;
public WrappedScalaResult(play.api.mvc.Result scalaResult) {
this.scalaResult = scalaResult;
}
#Override
public play.api.mvc.Result toScala() {
return scalaResult;
}
}
I want to create a link that would initiate a file download which would be asynchronous to the page itself, i.e. I want the page not to be locked during the file download. Should I make it be initiated outside wicket? Or is there something inside wicket that would let me set up a resource stream which would bypass the page locks?
Things I tried:
DownloadLink - locks the page, as stated in its doc. This was my starting point.
ResourceLink - did not state the locking explicitly in the doc, so I tried this, but it also locked the page.
At this point I've investigated the code of both links a bit and noticed they both schedule the download via ResourceStreamRequestHandler. Expecting that his kind of behavior could be just handler-specific I've attempted to schedule a custom handler I've written:
private void sendFile(final File file) throws IOException {
IRequestHandler fileDownloadHandler = new IRequestHandler() {
#Override
public void respond(IRequestCycle requestCycle) {
WebResponse response = (WebResponse) requestCycle.getResponse();
OutputStream outStream = response.getOutputStream();
response.setContentType("audio/x-wav");
response.setContentLength((int)file.length());
String fileName = "Somethingsomething.wav";
// sets HTTP header
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
byte[] byteBuffer = new byte[1024];
DataInputStream in = null;
try {
in = new DataInputStream(new FileInputStream(file));
int length = 0;
// reads the file's bytes and writes them to the response stream
while ((in != null) && ((length = in.read(byteBuffer)) != -1))
{
outStream.write(byteBuffer,0,length);
}
in.close();
outStream.close();
} catch (IOException e) {
throw new PortalError("IOException trying to write the response", e);
}
}
#Override
public void detach(IRequestCycle requestCycle) {
}
};
getRequestCycle().scheduleRequestHandlerAfterCurrent(fileDownloadHandler);
}
This did not quite work either, so I've investigated further. I've noticed that unlike I expected, the "scheduled" request handlers would not get executed on a separate request, as I expected, but on the same one. I figured that it must be that the page gets locked for the first handler and then remains locked while the second one is executing as well. So I've attempted to force the download handler into a separate request (via an ajax behaviour):
public void startDownload(AjaxRequestTarget target) throws DownloadTargetNotFoundException{
target.appendJavaScript("setTimeout(\"window.location.href='" + getCallbackUrl() + "'\", 100);");
}
#Override
public void onRequest() {
sendFile(getFile());
logger.debug("Download initiated");
}
I've found this here and hoped it could potentially be what I've been looking for. However, unsurprisingly so, the page gets locked still (I would imagine because the behaviour still has to be retrieved from the page, for which the page lock has to be acquired).
I'm at a loss where I should be looking next, especially after all this time trying to get a simple download link working. I was considering creating another web filter one layer above wicket, which could be signaled from within wicket to create the download after the wicket filter is finished with its work (and hence the page lock is already released), but that seems a bit excessive for a task like this.
Any suggestions are welcome.
You have to download from a resource, see
http://wicketinaction.com/2012/11/uploading-files-to-wicket-iresource/ and read http://wicket.apache.org/guide/guide/resources.html
A normal java file executes only those methods called in the main. But what does a servlet do? I thought maybe it executes down the file but I just tried to split up a HTTP servlets request and response but it doesn't work. What is a neat way of working with a servlet to read an input stream, then execute some functions which can call the response writer method?
Here was my tryout code:
public void requestReader(HttpServletRequest req) {
try {
int len = req.getContentLength();
byte[] input = new byte[len];
ServletInputStream sin = req.getInputStream();
int c, count = 0 ;
while ((c = sin.read(input, count, input.length-count)) != -1) {
count +=c;
}
sin.close();
String inString = new String(input);
int index = inString.indexOf("=");
String value = inString.substring(index + 1);
inputStream = URLDecoder.decode(value, "UTF-8");
} catch (IOException e) {
}
}//end of requestReader
public void responseWriter(HttpServletResponse resp) {
try{
resp.setStatus(HttpServletResponse.SC_OK);
OutputStreamWriter writer = new OutputStreamWriter(resp.getOutputStream());
writer.write("Working");
writer.flush();
writer.close();
} catch (IOException e) {
}
}//end of responseWriter
A normal java file executes only those methods called in the main.
A "Java file" does not execute anything. The JVM, started by the java command line tool, executes the main method.
But what does a servlet do? I thought maybe it executes down the file
A servlet runs inside a Servlet Container, e.g. Apache Tomcat, or Jetty. The container itself is started via a main method, it learns about servlet classes in its web.xml file, and it calls the service() method of the servlet when a request arrives.
What is a neat way of working with a servlet to read an input stream, then execute some functions which can call the response writer method?
That's exactly what a servlet does (though the headers of a HTTP request are parsed by the servlet container and passed to the servlet as part of the request object). What are you really trying to do?
If you're not running a servlet container, it makes no sense to use servlets.
No Java class simply executes methods sequentially.
If you want to use multiple methods, you must break up your functionality and explicitly call the other methods you want to use, just like you do in a standalone program.
Servlet execution starts with a request handler, generally doPost or doGet.
Here's a tutorial to read through, but there are countless others--just search for "servlet tutorial".
Methods are never executed sequentially. They are executed WHEN called.
The function of a servlet is to service HTTP requests from a web browser. For this, your servlet must implement a service() method and then call your methods from inside it.
You could also implement doPost() or doGet() but they only respond to the POST and GET commands.
You can start by looking here
Servlets are typically used in the context of a web server. This is in contrast with a "normal Java file" which is typically executed from the command line and starts with the main method.
In order to get your servlet to work, you need to make it part of a Java web application. If you've never done this before, it would be best to follow a tutorial about Java web applications.
Briefly, the doPost, doGet, or service methods of HttpServlet are roughly equivalent to the main method (though with some important differences such as the main method is entered once while service can be entered many times).
When a GET HTTP request comes in, and the servlet is mapped to the path of the request, then the servlet doGet method is called. If it's a POST, then doPost is called. You need to override one (or both) of these methods to do what you want with the request and the response.
Read the javadoc of HttpServlet to learn more.
HttpServlet already define methods you can implement for different type of http request:
doGet()
doPost()
doDelete()
doPut()
etc...
All these methods have a request and response parameter.
You can read requested data, call any service you want, then write the response using the httpServletResponse from the parameter.
You don't have to define your own methods like you did in your question.
To anyone interested, here is an update code that does work by passing the ServletResponse to another class:
public void doPost(HttpServletRequest req, HttpServletResponse resp) {
try {
int len = req.getContentLength();
byte[] input = new byte[len];
ServletInputStream sin = req.getInputStream();
int c, count = 0 ;
while ((c = sin.read(input, count, input.length-count)) != -1) {
count +=c;
}
sin.close();
String inString = new String(input);
int index = inString.indexOf("=");
String value = inString.substring(index + 1);
inputStream = URLDecoder.decode(value, "UTF-8");
} catch (IOException e) {
}
responseWriter(resp);
}//end of requestReader
public void responseWriter(HttpServletResponse resp) {
try{
resp.setStatus(HttpServletResponse.SC_OK);
OutputStreamWriter writer = new OutputStreamWriter(resp.getOutputStream());
writer.write("Working");
writer.flush();
writer.close();
} catch (IOException e) {
}
}//end of responseWriter
This was all I was trying to achieve when I asked the question.
I'm actually working on a GWT based website.
Now I'm stuck on how I should display images stored in a database on my website.
Basically I've a bytearray in my database, which I fetch using hibernate.
Now should I probably create an ... tag out of that data, but I don't know how
I'm using GWT in Java and Hibernate
Here is the solution. First you should encode the byte array by using com.google.gwt.user.server.Base64Utils.toBase64(byte[]) . But this method does not work for IE 7. and IE8 has 32kb limit.. IE9 does not have this limit.
here is the method on the server
public String getImageData(){
String base64 = Base64Utils.toBase64(imageByteArray);
base64 = "data:image/png;base64,"+base64;
return base64;
}
Here is the client method ;
#Override
public void onSuccess(String imageData) {
Image image = new Image(imageData);
RootPanel.get("image").add(image);
}
I don't know how GWT works, albeit you can map a servlet/controller which returns resourceStream.
For example if you map a servlet "imageViewer" which takes imageId param, request to image would become
/imageViewer?imageId=1234
Hibernate object would have reference to the blob, so you can return that.
Reference on UI would be
<img src="/imageViewer?imageId=1234"/>
Update: You may not be able to use Model as it is to return image, you would need an explicit controller or servlet which returns stream data.
In servlet you would do something like
// get reference to input stream
InputStream in = hibnerateObject.getImage();
// set MIME type etc
response.setContentType(mimeType);
OutputStream out = response.getOutputStream();
while ((len = in.read(buf)) >= 0)
out.write(buf, 0, len);
in.close();
out.close();
There is Image Widget in GWT. You can't do it client-side but you can call RPC to communicate with the server. Then it is simple CRUD application. In server connect to database with hibernate and return the Image to the client or it's url and on the client-side do something like that :
#Override
public void onSuccess(String imageUrl) {
Image image = new Image(imageUrl);
RootPanel.get("image").add(image);
}
#Override
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
That's all. Happy coding
I used the same approach as Gursel Koca suggested but could only get it to work using the Apache Base64 library, not (ironically) the GWT Base64Utils
String base64 = Base64.encodeBase64String(array);
base64 = "data:image/"+type+";base64," + base64;
return base64;
Also note that if you are updating an existing image or an image placeholder, the setURL method will overwrite your stylesheet, so make sure to grab that first:
String styleName = profilePicture.getStyleName();
profilePicture.setUrl(base64String);
profilePicture.setStyleName(styleName);
I'm writing to the browser window using servletResponse.getWriter().write(String).
But how do I clear the text which was written previously by some other similar write call?
The short answer is, you cannot -- once the browser receives the response, there is no way to take it back. (Unless there is some way to abnormally stop a HTTP response to cause the client to reload the page, or something to that extent.)
Probably the last place a response can be "cleared" in a sense, is using the ServletResponse.reset method, which according to the Servlet Specification, will reset the buffer of the servlet's response.
However, this method also seems to have a catch, as it will only work if the buffer has not been committed (i.e. sent to the client) by the ServletOutputStream's flush method.
You cannot. The best thing is to write to a buffer (StringWriter / StringBuilder) and then you can replace the written data any time. Only when you know for sure what is the response you can write the buffer's content to the response.
In the same matter, and reason to write the response this way and not to use some view technology for your output such as JSP, Velocity, FreeMarker, etc.?
If you have an immediate problem that you need to solve quickly, you could work around this design problem by increasing the size of the response buffer - you'll have to read your application server's docs to see if this is possible. However, this solution will not scale as you'll soon run into out-of-memory issues if you site traffic peaks.
No view technology will protect you from this issue. You should design your application to figure out what you're going to show the user before you start writing the response. That means doing all your DB access and business logic ahead of time. This is a common issue I've seen with convoluted system designs that use proxy objects that lazily access the database. E.g. ORM with Entity relationships are bad news if accessed from your view layer! There's not much you can do about an exception that happens 3/4 of the way into a rendered page.
Thinking about it, there might be some way to inject a page redirect via AJAX. Anyone ever heard of a solution like that?
Good luck with re-architecting your design!
I know the post is pretty old, but just thought of sharing my views on this.
I suppose you could actually use a Filter and a ServletResponseWrapper to wrap the response and pass it along the chain.
That is, You can have an output stream in the wrapper class and write to it instead of writing into the original response's output stream... you can clear the wrapper's output stream as and when you please and you can finally write to the original response's output stream when you are done with your processing.
For example,
public class MyResponseWrapper extends HttpServletResponseWrapper {
protected ByteArrayOutputStream baos = null;
protected ServletOutputStream stream = null;
protected PrintWriter writer = null;
protected HttpServletResponse origResponse = null;
public MyResponseWrapper( HttpServletResponse response ) {
super( response );
origResponse = response;
}
public ServletOutputStream getOutputStream()
throws IOException {
if( writer != null ) {
throw new IllegalStateException( "getWriter() has already been " +
"called for this response" );
}
if( stream == null ) {
baos = new ByteArrayOutputStream();
stream = new MyServletStream(baos);
}
return stream;
}
public PrintWriter getWriter()
throws IOException {
if( writer != null ) {
return writer;
}
if( stream != null ) {
throw new IllegalStateException( "getOutputStream() has already " +
"been called for this response" );
}
baos = new ByteArrayOutputStream();
stream = new MyServletStream(baos);
writer = new PrintWriter( stream );
return writer;
}
public void commitToResponse() {
origResponse.getOutputStream().write(baos.toByteArray());
origResponse.flush();
}
private static class MyServletStream extends ServletOutputStream {
ByteArrayOutputStream baos;
MyServletStream(ByteArrayOutputStream baos) {
this.baos = baos;
}
public void write(int param) throws IOException {
baos.write(param);
}
}
//other methods you want to implement
}