Java backend throws NoSuchFileException exception on multipart form file upload - javascript

I have a REACT frontend app and Java Spring backend. I send an image from frontend to backend but REST Controller throws the following error in Java:
java.nio.file.NoSuchFileException: C:\Users\User\AppData\Local\Temp\tomcat.8080.4543654899823294058\work\Tomcat\localhost\ROOT\upload_8189f9b4_9186_424d_b7c4_c4eec0f67e23_00000005.tmp
Controller:
#PostMapping(path="/add", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<Product> addProduct(#ModelAttribute Product product) throws IOException {
...
}
Product Model:
#Document(collection = "products" )
public class Product {
#Id
private String id;
#Field("title")
private String title;
...
#Field("images")
private List<ProductImages> images;
}
I don't even know how to dig it further, what's the issue here?
Images that I send are in multipart FormData with the following structure:
{ data: base64 buffer,
contentType: jpg/png/etc.
}
On the react frontend:
let formData = new FormData();
...
formData.append("images", this.state.images[0]);
...
axios.post(`${server_url}/product/add`,formData)...

Related

X-Total-Count missing header error in React Admin with Spring Boot API

I have my Spring Boot REST API. Link: "http://localhost:8080/api/components/component/list"
For the frontend, I am using React, above is the link that I want the "React Admin" app to consume.
Here is my Spring Boot's CORS Code, it is in a separate class called CorsConfig:
#Configuration
public class CorsConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry myCorsRegistry){
myCorsRegistry.addMapping("/**")
.allowedOrigins("http://localhost:3000") //frontend's link
.allowedHeaders("Access-Control-Allow-Origin","Access-Control-Allow-Header", "Access-Control-Expose-Headers", "Content-Range", "Content-Length", "Connection", "Content-Type", "X-Total-Count", "X-Content-Type-Options", "Set-Cookies", "*")
.allowedMethods("GET", "POST", "PUT", "HEAD", "OPTIONS", "PATCH")
.allowCredentials(true)
}
}
For my controller class I have the following:
#CrossOrigin("http://localhost:3000")
#RequestMapping("/api/components/component")
#RestController
public class Component{
#Autowired
//code...
}
Here is my React Code:
import React from 'react';
import { Admin,ListGuesser, Resource} from 'react-admin';
import jsonServerProvider from "ra-data-json-server";
const parentURL =
jsonServerProvider(`http://localhost:8080/api/components/component`);
function App() {
return(
<Admin dataProvider={parentURL}>
<Resource name="list" list={ListGuesser} />
</Admin>
);
}
Here is the error I am getting in my Chrome console:
The X-Total-Count header is missing in the HTTP Response. The jsonServer Data Provider expects
responses for lists of resources to contain this header with the total number of results to build the
pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers
header?
In my JavaScript code:
When I use restProvider, I get the "Content-Range header is missing in the HTTP Response" error
When I use jsonServerProvider, I get the "X-Total-Count header is missing in the HTTP Response" error
My Question:
How to fix the above error?
In the RestController add crossorigin base on your client
#CrossOrigin(origins = {"http://localhost:3000"}, exposedHeaders = "X-Total-Count")
Create a new class ConrolAdvice to send response
#ControllerAdvice
public class ResourceSizeAdvice implements ResponseBodyAdvice<Collection<?>> {
#Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
//Checks if this advice is applicable.
//In this case it applies to any endpoint which returns a collection.
return Collection.class.isAssignableFrom(returnType.getParameterType());
}
#Override
public Collection<?> beforeBodyWrite(Collection<?> body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
response.getHeaders().add("X-Total-Count", String.valueOf(body.size()));
return body;
}
}
Looks like the header to be used now is:
e.g. Content-Range: posts 0-24/319
I'm reading the Table name from the entity to expose this:
String tableName = page.getContent().get(0).getClass().getAnnotationsByType(Table.class)[0].name();
long minElement = page.getNumber() * page.getSize();
long maxElement = Math.min(minElement + page.getSize() - 1, page.getTotalElements() - 1);
long totalElements = page.getTotalElements();
String contentRange = String.format("%s %d-%d/%d", tableName, minElement, maxElement, totalElements);
response.getHeaders().add("Content-Range", contentRange);
On top of the Annotation for CORS mentioned above:
#CrossOrigin(origins = {"http://localhost:3000"}, exposedHeaders = "Content-Range")

Retrieve image using spring boot and angular 9 problem

i have problem with getting image from spring boot (webapp/images) to angular 9 using api rest and spring security jwt.
when i save my image it work ... i found it in the folder webapp/images
but when i try to get the image i have problem with showing it
Here is my code.
Saving image:
//region Save UserProfile
#PostMapping
public ResponseEntity<?> createUserProfile(#RequestParam("file") MultipartFile file, #Valid #RequestParam("userProfile") String userProfile)throws Exception{
boolean isExit = new File(context.getRealPath("/Images/")).exists();
if (!isExit)
{
new File (context.getRealPath("/Images/")).mkdir();
System.out.println("---Folder Was Created---");
}
String filename = file.getOriginalFilename();
String newFileName = FilenameUtils.getBaseName(filename)+"."+FilenameUtils.getExtension(filename);
File serverFile = new File (context.getRealPath("/Images/"+File.separator+newFileName));
try
{
System.out.println("Image");
FileUtils.writeByteArrayToFile(serverFile,file.getBytes());
}catch(Exception e) {
e.printStackTrace();
}
UserProfile userProfileMapper = new ObjectMapper().readValue(userProfile, UserProfile.class);
userProfileMapper.setUrlImage(newFileName);
UserProfile newUserProfile=iCommonService.save(userProfileMapper);
return new ResponseEntity<>("UserProfile was saved",HttpStatus.CREATED);
}
//endregion
Spring boot controller:
//USERPROFILE_IMAGE_BY_USER_UID= "/imageuserprofile/{userprofileuid}"
#GetMapping(path = APIName.USERPROFILE_IMAGE_BY_USER_UID)
public byte[] getPhoto(#PathVariable("userprofileuid") String userprofileuid) throws Exception{
UserProfile userProfile = iCommonService.findByUid(userprofileuid);
if(userProfile == null){
throw new CommonServiceException("User profile uid not found");
}
return Files.readAllBytes(Paths.get(context.getRealPath("/Images/")+userProfile.getUrlImage()));
}
Angular Service
private baseUrl = 'http://localhost:8080/userprofile';
public host :string = "http://localhost:8080";
getUserProfileImage(uid: string): Observable<any> {
return this.http.get(`${this.baseUrl}/imageuserprofile/${uid}`);
}
My Component
constructor(
public userProfileService: UserProfileService,
) {}
getImageUserProfile() {
this.userProfileService
.getUserProfileImage(this.userProfileUid)
.subscribe((image) => {
this.imageUserProfile =image;
});
}
In the Template i try with :
<img
class="profile-user-img img-responsive img-circle"
[src]= "'data:image/png;base64,'+imageUserProfile"
alt="User profile picture"
/>
this give me (data:image/png;base64,undefined:1 GET data:image/png;base64,undefined net::ERR_INVALID_URL)
Or
<img
class="profile-user-img img-responsive img-circle"
[src]= "imageUserProfile"
alt="User profile picture"
/>
this give me ("Unexpected token � in JSON at position 0")
also i try with
<img
class="profile-user-img img-responsive img-circle"
src= "{{this.userProfileService.host+'/userprofile/imageuserprofile/'+userProfileUid}}"
alt="User profile picture"
/>
this give me (GET http://localhost:8080/userprofile/imageuserprofile/2SGI2U8WXUVSfMdgZqhQrok66wLaU03y 403)
can some tell me what is im doing wrong or what.
thanks in advenced.
There are two things to be corrected here:
You are probably getting a 403 error because you are not passing the jwt auth token that is required in the headers of the http.get() request. I could tell certainly only if you share the code related to spring security where you have overridden default spring boot security config for implementing your jwt security.
Your http.get() should probably look something like this.
private baseUrl = 'http://localhost:8080/userprofile';
public host :string = "http://localhost:8080";
getUserProfileImage(uid: string): Observable<any> {
headers:HttpHeaders=new HttpHeaders().set(<jwt header name>,<token value>)
return this.http.get(`${this.baseUrl}/imageuserprofile/${uid}`,{headers:headers});
}
Coming to the second part about how to properly process and display the image you receive
from angular http.get(), this stack answer will help you
GET data:image/png;base64,{{image}} net::ERR_INVALID_URL

Passing a complex FormData from angular 5 to Java Spring 3

I'm trying to insert into a FormData an array of arrays and a string, however java seems to not receive it , I have no log error in my Java server however I have a 500 Internal Server Error in my JavaScript console.
Here is the code for my controller :
#RequestMapping(value = "/getReporting", method = RequestMethod.POST)
#ResponseBody
public void getReporting(#RequestParam RecommendationForm form, #RequestParam String type, HttpServletResponse response) throws ApcException {
System.out.println("prova");
Map.Entry<String, byte[]> result = this.reportingService.getReporting(form,type);
try {
response.setHeader(//
"Content-Disposition",//
"attachment; filename=" +"bobo.xlsx");
response.setContentType("Application/x");
response.getOutputStream().write(result.getValue());
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And here is my service in Angular :
public getExcel(form: FormData): Observable<HttpResponse<Blob>> {
return this.http.post('/SV-AUD/api/reporting/getReporting', form, {observe: 'response', responseType: 'blob'});
}
And the component where I append the info in the formData :
form: FormGroup = this._fb.group(
{
hello1: [],
hello2: [],
hello3: [],
hello4: [],
hello5: [],
hello6: [],
hello7: [],
hello8: [],
hello9: [],
}
);
exportExcel() {
const formData: FormData = new FormData();
formData.append('form', this.form.getRawValue());
if (this.detailedType) {
formData.append('type', 'detailed');
} else {
formData.append('type', 'list');
}
this.reportingService.getExcel(formData).subscribe(data => {
const ctHeader = data.headers.get('content-disposition');
if (ctHeader) {
const filename = ctHeader.split('=')[1];
saveAs(data.body, filename);
}
});
}
The behavior that you are describing suggests that Spring is unable to bind your #RequestParam parameters of your getReporting method to the incoming request.
That means that the data that you are posting from the Angular side does not match up with what is expected on the Spring side.
Unless it's a typo, I'm guessing that the problem is this line in your component's source code, which does nothing (and should be a syntax error due to mis-matched parens):
(this.form.getRawValue()));
I'm guessing that it should be :
formData.append('form', (this.form.getRawValue()));

Odata with Asp.net and angularjs

I am following up in the course AngularJS Front to Back with Web API using ASP.net, we are trying to do queries using ODATA so i added this code in the ProductController in the WebAPI
// GET: api/Products
[EnableQuery()]
public IQueryable<Product> Get()
{
var productRepository = new ProductRepository();
return productRepository.Retrieve().AsQueryable();
}
then added the below code in the productcontroller in the angular code:
function ProductListCtrl(productResource) {
var vm = this;
productResource.query({$skip:1, $top:3}, function (data) {
vm.products = data;
})
but when I try to run it gives me the below error:
angular.js:12701 GET http://localhost:59302//api/products?$skip=1&$top=3 400 (Bad Request)
Possibly unhandled rejection: {"data":{"message":"The query specified in the URI is not valid. No non-OData HTTP route registered.","exceptionMessage":"No non-OData HTTP route registered.",.....
Maybe you don't have odataConfiguration?? Where's you EDM configuration?
In your config file you need something like that:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code:
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
}
}

Angularjs, JavaEE and http request with inherited objects?

I work on webapp and can't find solution or example of my problem.
I use AngularJS, RestServis and JavaEE . My problem is how to send inherited object with superObject
In java I have two classes:
public class User{
protected String userName;
protected String userSurename;
..
..
}
Second class is a subclass
public class Worker extends User{
protected int idWorker;
protected String position;
..
..
}
in Angular controller I have
$scope.user = {
userName : "jon" ,
userSurename :"dep" }
$scope.worker= {
idWorker: 88 ,
position: "seller" }
and I use http protocol to send data on server side like this
this.saveWorker = function(worker) {
return $http({
method:'post',
url:this.apiBasicUrl,
contentType: "application/json",
data: worker
});
};
How in Angular in data to put one object and on Java side get worker object with user data also ? Can I , object like in java , make in angular with inherited ?
On Angular side, I suggest using $resource for communication with REST API:
var Worker = $resource('/worker/:workerId', {workerId:'#id'});
//get
var worker = Worker.get({workerId:123}, function() {
worker.abc = true;
//save
worker.$save();
});
On server side you should have a REST endpoint that is supposed to pick up these objects:
#Path("/worker")
public class WorkerService {
#GET
#Path("{workerId}")
public Worker getWorker(#PathParm("workerId") Integer workerId) {
//implement
}
#POST
public void saveWorker(Worker worker) {
//implement
}
}
This might not work out of the box. You will most likely need Jackson provider to enable REST to "translate" JSON into Java objects.
See this example: http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/

Categories

Resources