In my JSP/ Servlet setup, for displaying user profile images I am directing the img tag to get the image from servlet by specifying servlet URL in src tag and then returning image in response from servlet.
Sevlet does below things upon receiving an image request,
It gets the image from database in BLOB format
Prepares image from the byte[] and
returns the image in response object with appropriate headers.
My problem is since Signup page doesn't has image upload option so new users don't have their image in database i.e. so the BLOB is NULL. How can I display a default image for all such users ?
EDIT
Based on comments received I just wanted to note that. I am aware of the solutions where we set the default value either in database (while creating the user) or return the default image array when there is NULL in database. I am already using the later case. By this question I just wanted to discuss about any other possible solutions.
One option could be to return HTTP error 404 "Not found" when the user don't have an image. It seems quite logical to me, since there really is no image for the user.
public void doGet(HttpServletRequest request, HttpServletResponse response) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
Then in your HTML you can handle this case using the onerror Event to set the default image:
<img src="servletUrl" onerror="this.src='default.png'" width="150" height="150" />
In this way the servlet only sends user images and does not do any special logic if the user doesn't have one.
Related
The argument has been made and settled on numerous occasions: Blobstore is better than DataStore for storing images. Now say I have an app similar to Instagram or Facebook or Yelp or any of those apps that are image intensive. In my particular case the ideal model would be
public class IdealPostModel{
Integer userId;
String synopsys;
Blob image;
...//more data/fields about the post
}
But since I must use the BlobStore, my model does not have a blob but instead a URL or BlobKey. The heavy catch is that to send a post (i.e. save a post to server) the app must -- in that order --
Send all the non-blob data to the server.
Wait for server to respond with BlobstoreUtils.generateServingUrl(null) data
Send the images to the BlobStore
Have BlobStore send response to my server with the BlobKey or url of the image
Store the BlobKey/url in my DataStore entity
That's a lot of handshakes!!!
Is there a way to send all the data to the server in step one: strings and image. And then from there have the server do everything else? Of course I am here hoping to reduce the amount of work. I image App Engine must be quite mature by now and there has to be a simpler way than my architecture.
Now of course I am here because I am experiencing situations where the data is saved but the BlobKey or URL is not being saved to the Entity. It happens about 10% of the time. Or maybe less, but it does feel like 10%. It's driving my users insane, which means it's driving me even more insane since I don't want to lose my users.
Ideally
App sends everything to server in one call: image and metadata such as userId and synopsys
Server somehow gets a blob key from Blobstore
Server sends image to blobstore, to be stored at the provided blob key, and server sends other data to DataStore, also including the blob key in the datastore.
Update
public static String generateServingUrl(String path) {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
return blobstoreService.createUploadUrl(null == path ? "/upload" : path);
}
This is a snippet on my server.
The workflow is different. Given your example:
There is "Post" button and "Attach an image" button under a form for a new post.
When a user hits the Attach button, you ask a user to select a file and save it to the BlobStore (or Google Cloud Storage). There is no need to call BlobstoreUtils.generateServingUrl(null) - you need to get an upload URL. When a call returns a key, you store it in the Post object.
When a user hits the Post button, you save the Post - including the image key (keys) in the Datastore. Thus, the entire workflow takes only two calls.
If a user hits the Cancel button - remember to delete the uploaded image(s) if any, or they will be orphaned. The tricky part is to delete these images if a user simply left your app or lost connection.
If you want, you can reverse the process - save post first, then let users attach images. This is not what most users expect, but it solves the problem with orphaned images.
You actually cand send everything in a single request.
Bear in mind that when you send a blob using a URL gotten by calling blobstoreService.createUploadUrl("/yourservingurl") , GAE actually makes a first request to a different URL, stores the blob and then calls /yourservingurl passing you the blobkeys which you can retrive by doing:
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("myFile");
So in effect all other form values will be lost after that first request, BUT if you can build that URL dynamically eg
blobstoreService.createUploadUrl("/yourservingurl?param1=a¶m2=b")
then you can get back those parameters on your Servlet and persist everything (including the blobkey of the already stored blob) at once, making much fewer calls to the datastore.
UPDATE:
the steps would be
1) Gather all parameters on the client side and create an upload URL with those params eg: blobstoreService.createUploadUrl("/yourservingurl?userId=989787") . GAE will generate a unique URL for that specific request.
when you commit the form, GAE will persist the blobs and call /yourservingurl
2) On the Servlet serving /yourservingurl you'll get all the blobkeys form files you uploaded by using : blobstoreService.getUploads(request) AND you can get the parameters you included with the standard request.getParameter("userId")
3) Now in your servlet you have all the parameters (eg userId) you sent plus the blobkey, you can persist your Post object in one call.
I have to print on a jsp page some images that i get in the form of InputStream.
First i have servlet that passes a variable containing an InputStream to a jsp page, this way:
request.setAttribute("Image", InputStream);
request.getRequestDispatcher(pagename).include(request, response);
In my jsp page i have this to get that InputStream:
${requestScope.VariableContainingInputStream}
To turn that InputStream into an image i should use a servlet this way:
<img src="ServletName">
How can i pass that InputStream to that servlet?
How can i pass that InputStream to that servlet?
You wouldn't. Your JSP would create a temporary (or permanent) file and would write the contents of the InputStream to it. You'd then provide an endpoint that would serve up the content of that file.
You would then provide the URL to that endpoint in your JSP's <img> element.
If you get it as an InputStream, I assume the image is generated dynamically or generally speaking that you have something that gives it to you depending of a number of parameters.
You should think about how a normal (or stupid ...) browser will work :
the user clicks on a link, a submit button or pass an url in adress bar
the browser generate the corresponding request and sends it to the server
the server generate a (generally HTML) page containing links to images and sends it back to browser
the browser analyzes the page, and sends separate requests for the images
the server sends back the image one for each request
the browser display full page containing images
(you could replace images by css pages, js scrips, or any other resources)
So you should not get the input stream at the time of running your jsp to compose the HTML page but write in it <image source=/ImageServlet_url?params_for_current_image/>
Then when the browser will ask for the image, the image servlet will ask for the InputStream and put it directly in response body, with the correct type in the response headers.
This is by far the most robust way of solving your problem. If really it is not an option and the InputStream is only disponible at the moment of running the jsp, you must put in in a session attribute. Then when the ImageServlet will be called, it will look for it in the session and sends it. The problem is that an InputStream in not necessarily Serializable and it is unsafe to put non serializable items in session. So you should :
set a global Hash<String, InputStream> somewhere in your app
when trying to put the InputStream in session, actually put in in the hash (with a unique key) and store the key in session
when getting the InputStream from session, get the key from the session and fetch the InputStream from the hash ... and do not forget to remove it form the hash ...
I strongly advice you to stick to the first solution, not speaking or network errors or power outages between the request of the HTML page and the image ...
I'm trying to update a particular 'div' with profile pic and some html content without refreshing the whole page when the user successfully authenticated.
I
1) Stored the profile pic while user registration process to database( I could save it to a file system, but here my requirement is to store it in database blob)
2) Could able to retrieve image as a binary stream from database and display image alone(without any html content) to html page
I went through a couple of Answers in stackoverflow, they say we can't serve image+html content to the same webpage('div' in my case) from one servlet!
Help me to with how to serve image+html content to update just a 'div' of html page?
How about writing 2 servlets, one to take in the image and write it to the database and another one to get the image and pass it back in the response output stream which you can call from the webpage via an ajax call.
Get the output stream of the HttpServletResponse object passed into your servlet and use write method to pass back your image. I would encode your image to base 64 and wrap it with some html.
public void service(HttpServletRequest request, HttpServletResponse response) {
response.getWriter().println("html and base64 string");
response.getWriter().close();
}
I have a file directory on my server with images. The name of the image is associated with an items table. Item ID#1, will have a corresponding image "1.png".
Not all items have an image so if the app checks, it will find nothing on some of them. In that case, I want an if check to show a default image.
My question: with only a URL available, how can I check if the url leads to an image or if it leads to nothing/blank/null?
I would suggest asking for the Head of the image request simply because it is faster.
Non Picasso :
HttpClient client= new DefaultHttpClient();
HttpHead headMethod = new HttpHead(urlToImage);
HttpResponse response = client.execute(headMethod);
if(response.getStatusLine().getStatusCode== HttpStatus.SC_NOT_FOUND) {
// Image does not exist, show a placeholder or something
} else {
// load image into the view.
}
Picasso : (nothing to do with the head version, but this is an easy alternative to handle it, also look at the Callback that Picasso can take in to fine tune the success/error)
Picasso.with(context).load(urlToImage).into(imageView).placeholder(R.drawable.user_placeholder).error(R.drawable.user_placeholder_error);
References:
Apache HttpHead from Android's SDK Reference
Apache HttpStatus from Android's SDK Reference
Square Picasso
Assuming you are talking about a scenario where you are attempting to fetch the image over HTTP / HTTPS ...
The simple approach is to just attempt to fetch the image. Then you check the response to see what the response status code is and what the content type is. If they 200 and "image/png" respectively then you have the image. If the status code is 404 then the image does not exist. If neither, then it is a reasonable assumption that "something has gone wrong" at the server end.
The linked question has code for doing this kind of thing.
The problem is that you are somewhat dependent on what the server does when you attempt to fetch an image that isn't there. It could plausibly:
substitute a default image of its own
return an error page, with or without setting a 404 status code
redirect you to an error page, which means that the status code would be a 3xx,
fail, resulting in a 5xx response, or even
seem to succeed but return an empty body, or a body whose actual contents doesn't match the response "content-type" header.
If you implemented the server, or you are dealing directly with the implementers, you can make assumptions about what it will do. But if your code has to work against any server, then it needs to be more complicated ... and more defensive.
I want to allow the user to save file using mvc portlet. In my code i am making an ajax call hence it has to be a resource response.
response.setContentType( "application/octet-stream" );
response.setProperty("Content-Disposition","attachment; filename=\""+fname+"\"");
response.setContentLength(b.length);
OutputStream po= response.getPortletOutputStream();
po.write(b,0,b.length);
po.flush();
po.close();
In ajax response when i do alert(resp), I am getting the whole content of my file in alert but still not getting any option for download.
Please help and thanks in advance ;)
Well, since you get the response, you need to allow the user to download it. You can for example use the HTML data: protocol and redirect the browser to smt. like
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAA...
for a PNG image.
Anyway, can't you use a normal request to a portlet? It's trivial then.