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
Related
I'm working in Spring Boot project where I have two entities.
Client entity :
#Entity
public class Client {
// mapping annotation ...
private Long id;
// mapping annotation ...
private String firstName;
// mapping annotation ...
private String lastName;
// mapping annotation ...
private Set<Document> listDocument;
....
}
Document entity :
#Entity
public class Document{
// mapping annotation ...
private Long id;
// mapping annotation ...
private String name;
// mapping annotation ...
private int size;
// mapping annotation ...
private Client client;
....
}
My app has a form where I set all the information of the clients. Also, I have an input file where I have to upload multiple documents.So, when I click on submit button I have to persist the client information into the database along with all information (doc name,size..) about documents (with client Id) should be persisted in database and then files to be uploaded to the server.
I'm using Spring Boot with Angular, I'm not asking for code but I just want to know what will the best approach to achieve this according to the best practices.
I also had a similar Use Case. We have done this with File Zipping approach (require less storage, fast for small documents ). When the Client uploads the documents we create the new Zip file and named it in a unique way.
(not changing the names of original documents). For example, you can give a unique name with clientID + uploadTime.
Now to store there can be multiple ways (for rapid document retrieval)
Create only one directory (not an ideal way)
Create directories according to ClientId
Create directories according to UploadTime (DayWise, MonthWise)
If all the documents are uploaded successfully then you can save the information of documents in the table. Note that storing the path of a document can create a problem if the path changes in future so store only name of the document. As here you need to store details of each document you can create two tables. One table with id(pk), client Id, zip filename another with id(fk), document name, size etc.
you can configure max file-size, max request-size as below in application properties
MULTIPART (MultipartProperties)
spring.servlet.multipart.enabled=true # Whether to enable support of multipart uploads.
spring.servlet.multipart.file-size-threshold=0B # Threshold after which files are written to disk.
spring.servlet.multipart.location= # Intermediate location of uploaded files.
spring.servlet.multipart.max-file-size=1MB # Max file size.
spring.servlet.multipart.max-request-size=10MB # Max request size.
spring.servlet.multipart.resolve-lazily=false # Whether to resolve the multipart request lazily at the time of file or parameter access.
I did not understand the essense of the question.
In my opinion, it's necessary to upload files to the storage first. Operation of upload should be transactional (all or nothing). Error during any file upload fail whole upload. If the upload was successful - then save the information about files to the database.
I suggest to store the following additional information about uploaded files:
Date and time the file was uploaded
Id of the request. To know that multiple files have been uploaded within one request. You can use time in millis System.currentTimeMillis() or UUID UUID.randomUUID().toString()
Also, if the system contains a lot of files - I recommend storing files in separate directories to speed up the search. You can store to directories by the time of creation (for example every month new directory), or by the user id. It all depends on the search criteria for the files.
I would recommend you to rename files before store with any unique id (UUID for example) to avoid collisions. Of course you should store original and renamed file names in the database. Also this approach will not allow user to pick up the file name if the directory with files will be open. I mean that users can't guess alien files https://file-storage/user-john-dou/logo.jpg
If you are working with images you can think about resize before store.
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.
When fetching a HTML file from Spring Boot back-end via its API with Angular 4 app on the front-end, HTML tag attributes of type id, name, data-* are stripped away, but class attribute type remains. What's the reason for this, as I can't seem to find it?
If you mean the attrs are stripped when you bind to the innerHTML of an element in a template, it seems those attributes are not allowed by the sanitizer. Probably mostly because they're not presentionally useful in an Angular app. I don't know if id and data are considered potentially unsafe too. I know forms, inputs, buttons etc. are so name is useless.
The allowed attrs are listed in html_sanitizer.ts (full source):
const HTML_ATTRS = tagSet('abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,'
+ 'compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,' + 'ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,' + 'scope,scrolling,shape,size,sizes,span,srclang,start,summary,tabindex,target,title,translate,type,usemap,' +
'valign,value,vspace,width');
If you really need id, name or data attributes (why would you really?) and can trust your html 110%, ie. it's not originated from any user input or you have already sanitized it serverside, you can call DomSanitizer.bypassSecurityTrustHtml() with it before binding (or in a pipe) to leave the html untouched.
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 am using the Workflow Services Java API (11.1.1) for SOA Suite to access and manipulate human tasks. I would like to be able to access and add file attachments to existing human tasks. I am using the methods provided in the AttachmentType interface.
When adding an attachment, the problem I am running into is that an attachment does get created and associated with the task, however it is empty and has no content. I have attempted both setting the input stream of the attachment, as well as the content string and in each case have had no success (and setting the content string results in an exception when trying to update the corresponding task).
I have successfully added and accessed an attachment using the worklist application, however when trying to access the content of this attachment through code I receive an object with mostly null/0 values throughout, apart from the attachment name.
The code I am using to access attachments resembles:
List attachments = taskWithAttachments.getAttachment();
for(Object o : attachments){
AttachmentType a = (AttachmentType) o;
String content = a.getContent(); // NULL
InputStream str = a.getInputStream(); // NULL
String name = a.getName(); // Has the attachment name
String mime = a.getMimeType(); // Has the mime type
long size = a.getSize(); // 0
...
}
As the API's are not overly rich in documentation I may well be using them incorrectly. I would really appreciate any help/suggestions/alternatives in dealing with BPEL task attachments.
Thanks
After contacting Oracle for support, it turns out that the attachments portion of the Workflow API is broken in the current release. The fix will be included in a future release.