In our app there are two ways we serve images.
The first is through asset pipeline and second is fetching from database.
For the main company header logo we serve it from asset pipeline.
The gsp code looks like this
<img src="${resource(dir: 'images', file: 'logo.png')}" />
which renders in html to
<img src="/roadrace/assets/logo-addd262d2fffbdf8d868181896bf1698.png">
When the browser fetches this it is correctly memory cached as indicated in this request and marked by red box.
at other place where we display event image
the code look likes this
<img src="https://.../roadrace/uploads/logos/h1FdUah7vXGqTkq.jpg?1676524906000" id="logo">
this makes get request to this controller action
def uploads(String path) {
FileData imageData = FileData.findByPath("/${path}")
if (!imageData) {
response.sendError(404)
return
}
response.contentType = URLConnection.guessContentTypeFromName(path) ?: 'application/octet-stream'
response.getOutputStream().withCloseable {out ->
out.write(imageData.data)
out.flush()
}
}
you can see we are first fetching the image data using FileData domain which has data field which is of type byte[] which is written to response.
file data is defined as
class FileData {
String path
byte[] data
static constraints = {
path blank: false, unique: true
data nullable: false, maxSize: 16_777_215
}
}
so here how can we add response header so that this image is also browser cached?
since we are using images only in one place, it is best not to use cache plugins to keep the app lighter.
Thanks for the help!
Related
I am developing a rest api using spring boot.
I have an upload image service which stores images in my project workspace and image url in stored in db.
I have an entity product which has a list of images. Now I have to return images back to the angular client.
I have two questions in mind:
Q1. Should I return just a list of image urls to the client? If yes how should client render images from those urls.
Q2. OR Should I return list of images itself? If yes please show me logic which is fast and efficient.
Q3. OR Should I return individual image one by one? If yes please tell me how.
Update:
Note: Since, Rest api is on one machine and Angular client is on another machine. I think that the image url needs some kind of prefix:
Suppose my project is in E:/myproject/ and images are in E:/myproject/images/image-name.jpg, so what should be prefix for image url.
Q1. Should I return just a list of image urls to the client? If yes how should client render images from those urls.
THIS. Since all you need to do next is to give those urls <img src="something.png" /> tags in the front end. This will also free the server from the responsibility of downloading the image and service it to the clients.
Q2. OR Should I return list of images itself? If yes please show me logic which is fast and efficient.
This is possible but very hard. I don't advise doing this since this will make the system download the image twice: first is from file storage to the backend, then 2nd is from backend to frontend.
Q3. OR Should I return individual image one by one? If yes please tell me how.
This is the approach you need to do if the images needs individual security when downloading. Securing your image downloads is possible with the 1st approach that you given, and again, this approach will make you download the image twice.
Q1. Should I return just a list of image urls to the client? If yes how should client render images from those urls.
Ans : Return the list of urls to angular . Angular will use this code.
<div *ngFor="let image of images">
<img src={{image.ImagePath}} />
</div>
It will automatically fetch the images present at the url path
private static final Map<String, MediaType> TYPE_MAP = new HashMap();
static {
TYPE_MAP.put("pdf", MediaType.APPLICATION_PDF);
TYPE_MAP.put("gif", MediaType.IMAGE_GIF);
TYPE_MAP.put("jpg", MediaType.IMAGE_JPEG);
TYPE_MAP.put("jpeg", MediaType.IMAGE_JPEG);
TYPE_MAP.put("png", MediaType.IMAGE_PNG);
TYPE_MAP.put("html", MediaType.TEXT_HTML);
TYPE_MAP.put("xls", MediaType.parseMediaType("application/vnd.ms-excel"));
TYPE_MAP.put("xlsx", MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
}
#GetMapping(value = "/preview")
public ResponseEntity<Resource> previewFile(#RequestParam String filePath) {
Resource resource = new UrlResource(Paths.get(filePath).toUri());
String fileName = testFile.png;
String extension = png;
MediaType mediaType = TYPE_MAP.getOrDefault(extension,MediaType.APPLICATION_OCTET_STREAM);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "filename=\"" + fileName + "\"")
.contentType(mediaType)
.body(file);
}
Send filePath to the angular client and use this service in order to preview that file.
I'm working on a application in which users can update their information. For the moment, RFC 6902 Json-patch is used to update textual information (firstname, lastname, phone...) via a basic HTML Form.
User can now add images to their profile. Is there any way to use Json-patch to perform multipart operations ?
Note : The images are stored in a file system. So in the client side, only the image path is given and it can be updated only after the form submission. My dto is as below :
public class ProfileDto {
private Integer id;
private String firstname;
private String lastname;
private String defaultMedia; // <-- image path
...
}
Solution to which I think :
Since defaultMedia is of type String, Json-patch can be used to update the image path. The idea is when the form is submitted, perform a Multipart POST request to upload the image and get its URL. Then set defaultMedia of my DTO to the new URL.
This solution can create unsued images in the case when a error happened server side on form submission. So I need to add something to clean the file system.
Is there any easier solution to meet my needs ?
I'm using :
Spring Boot : 1.5.1
Angular 2 : 2.4.5
I have a canvas painted by the user.
In the JavaScript I do:
var data = canvas.toDataURL().substr(22);
// snipped code that sets up xhr POST to "d/"
var params = "img=" + encodeURIComponent(data);
xhr.send(params);
I substr(22) to get rid of "data:image/png;base64,"
Then in app engine I do:
doodle.setProperty("img", new Text(req.getParameter("img")));
So I am setting the img property of the doodle Entity to the canvas.toDataURL().substr(22)
Now, when I want to retrieve the image, I do:
if (debugimg) {
resp.setContentType("text/plain");
resp.getWriter().print(((Text)groove.getProperty("img")).getValue());
}
else {
resp.setContentType("image/png;base64");
resp.getWriter().print(((Text)groove.getProperty("img")).getValue());
}
But for the life of me, the image never comes up.
Here is an example. I drew this, and can save it and render it in JavaScript.
https://yougotadoodle.appspot.com/d.jsp?id=1483002
If I use debugimg, this is what is being saved:
http://yougotadoodle.appspot.com/d?id=1483002&img=true&debugimg=true
But when I try to serve it with setContentType("image/png;base64") or even just "image/png" you get a broken picture:
http://yougotadoodle.appspot.com/d?id=1483002&img=true
I have tried a few different things, including not substr(22)ing it. Any ideas?
I tried using a Blob(), so storing it like this:
doodle.setProperty("img", new Blob(req.getParameter("img").getBytes()));
and reading it like this:
resp.getWriter().print(((Blob)groove.getProperty("img")).getBytes());
But that seemed to spit out somethign like this:
[B#1f11e0f
You have to decode this string before serving it as image/png because it is the Base64 encoded version.
I tested it locally in Python and your Hello SO! worked perfectly after decoding the given string. I'm not sure how to do it in Java but it should be fairly easy.
Here are three code snippets that have worked for me on the JS side (jpg) through the put to a blob property. May not be optimal, but it does work. HTH. -stevep
Create canvas render:
imgFinalData = canvas.toDataURL('image/jpg', 1.0);
Setup variable for POST to GAE:
f64 = imgFinalData.substr(imgFinalData.indexOf(',')+1).toString();
Post to GAE (fd is an array used to store mutiple POST vars):
fd.push('bytes=' + escape(f64));
//Here is the call with fd that handles the post:
postXmlHttpRequest(url, fd.join('&'), handlePostFinal);
One the GAE side (Python):
Property that stores POST data (line from entity class):
bytes = db.BlobProperty(required=True, indexed=False)
How the post data is processed b/4 put:
data = urllib.unquote(self.request.get('bytes'))
data = data.replace(' ','+')
bytes = base64.b64decode(data + '=' * (4 - len(data) % 4))
Property line inside the entity statement for put:
bytes = db.Blob(bytes),
I want to write an excel and send it to the user as a response in an application using Play framework 1.x. But I am not sure how to set the response content-type/MIME-type for returning doc or excel file.
Let me know the steps for this.
From the documentation:
To serve binary data, such as a file stored on the server, use the renderBinary method. For example, if you have a User model with a play.db.jpa.Blob photo property, add a controller method to load the model object and render the image with the stored MIME type:
public static void userPhoto(long id) {
final User user = User.findById(id);
response.setContentTypeIfNotSet(user.photo.type());
java.io.InputStream binaryData = user.photo.get();
renderBinary(binaryData);
}
I have a Struts2 jsp page their i am sending one image, Temporary file path is comming to my java class after form submission but i do not know how can to save that path in db by changing it to Blob type.. Please consider this image columns is of blob type in my database table..
Here is the output what am getting in my Javaclass after the form submission:
My image path:
F:\Documents and Settings\software.netbeans\7.0\apache-tomcat-7.0.11_base\work\Catalina\localhost\AIGSA\upload__214d4f3e_136e8b74d9c__7fff_00000021.tmp 105542
filenames:
* Winter.jpg
Code:
for (File u: repImage)
{
System.out.println("*** "+u+"\t"+u.length());
}
int saveToDb= mo.addMembers(memberName, repImage);
How can I send my form Image to this {repImage Name, so that it will be easy to save it so my db
am not sure, but try:
int saveToDb= mo.addMembers( memberName, repImage.getBytes() );
If I understand your question properly, you want to store the binary data in your database. I'd say this is a bad idea in the first place for multiple reasons. A better method would be to reference a relative path that you can then use in your web application or the file system directly. Better yet, just store the reference to the location in Amazon/S3 where you want to save it/use it.
Regardless, to answer your question you would want to use ByteArrayOutputStream.