I need a simple File Upload (JavaScript code example) from NodeJS to Java Spring framework method as followed.
Any help (approach) would be very much appreciated !
Java Code in Spring framework:
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResponseEntity<FileJobResultBase> upload(HttpServletRequest httpServletRequest
) throws IOException {
try {
String storageName = httpServletRequest.getHeader("storageName");
String path = httpServletRequest.getHeader("path");
String fileName = httpServletRequest.getHeader("fileName");
String fileType = httpServletRequest.getHeader("fileType");
String context = httpServletRequest.getHeader("context");
String organization = httpServletRequest.getHeader("organization");
byte[] bytes = IOUtils.toByteArray(httpServletRequest.getInputStream());
FileJobResultBase fileJobResultBase = fileManagerService.upload(bytes, storageName, path, fileName, fileType == null ? "unknown" : fileType,authorization,organization, context);
return new ResponseEntity<>(fileJobResultBase, HttpStatus.OK);
} catch (Exception e) {
return exceptionHandling( e);
}
}
Currently my NodeJS code (but it's no good)
module.exports = {
create : function(req, res) {
var file = Object.keys(req.body.file).map(function(value, index) { return [value]; });
var headerSignature = APISigningService.getHeaderSignature();
}
Related
Currently, I try to send an image file in JPEG format to Angular. However, I'm getting the following error when I send it out through Postman.
class
org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile
cannot be cast to class java.lang.String
(org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile
is in unnamed module of loader 'app'; java.lang.String is in module
java.base of loader 'bootstrap')
The idea is to upload this image into cloudinary repository.
Here my code of the REST API:
#PostMapping("/uploads")
public ResponseEntity<?> upload(MultipartFile imagen) throws Exception {
Map<String, Object> response = new HashMap<>();
File conversion = new File(imagen.getOriginalFilename());
imagen.transferTo(conversion);
Cloudinary cloudinary = new Cloudinary();
cloudinary.uploader().upload("C:\\Users\\Dell\\Pictures\\"+conversion.getName(), ObjectUtils.asMap("public_id", imagen,
"api_key", "xxxxxxxxxxxxxxx", "api_secret", "xxxxxxxxxxxxxxxxxxxxxx", "cloud_name", "xxxxxxx"));
return new ResponseEntity<Map<String, Object>>(HttpStatus.CREATED);
}
Any Suggest will be appreciated
Code in Angular service Layer called paciente.services.ts
#Injectable({
providedIn: 'root'
})
export class PacienteService extends GenericService<Paciente> {
private pacienteCambio: Subject<Paciente[]> = new Subject<Paciente[]>
();
private mensajeCambio: Subject<string> = new Subject<string>();
constructor(protected http: HttpClient) {
super(
http,
`${environment.HOST}/pacientes/uploads`);
}
listarPacientes(){
return this.http.get<any>(`${this.url}`);
}
listarPageable(p: number, s:number){
return this.http.get<any>(`${this.url}/pageable?
page=${p}&size=${s}`);
}
subirImagen(archivo: string){
return this.http.post(`${this.url}/${archivo}`,archivo);
}
obtenerURLImagen(nombreImagen: String){
return this.http.get<Paciente[]>
(`${this.url}/descripcionAssets/${nombreImagen}`);
}
listar(){
return this.http.get<Paciente[]>(this.url);
}
listarPorId(id: number){
return this.http.get<Paciente>(`${this.url}/${id}`);
}
registrar(paciente: Paciente){
return this.http.post(this.url, paciente);
}
modificar(paciente: Paciente){
return this.http.put(this.url, paciente);
}
eliminar(id: number){
return this.http.delete(`${this.url}/${id}`);
}
//////////////////////////
getPacienteCambio(){
return this.pacienteCambio.asObservable();
}
setPacienteCambio(lista: Paciente[]){
this.pacienteCambio.next(lista);
}
getMensajeCambio(){
return this.mensajeCambio.asObservable();
}
setMensajeCambio(msj: string){
this.mensajeCambio.next(msj);
}
}
And this is the component where I setup the REST API subirImagen
export class PacienteEdicionComponent implements OnInit {
id: number = 0;
edicion: boolean = false;
nombreArchivo: File;
form: FormGroup;
public archivos: any = []
public files: NgxFileDropEntry[] = [];
constructor(
private route: ActivatedRoute,
private router: Router,
private pacienteService: PacienteService,
private sanitizer: DomSanitizer
) { }
ngOnInit(): void {
this.form = new FormGroup({
'id': new FormControl(0),
'nombres': new FormControl(''),
'apellidos': new FormControl(''),
'dni': new FormControl(''),
'telefono': new FormControl(''),
'direccion': new FormControl(''),
'fondo-imagen': new FormControl(''),
'email': new FormControl(''),
});
this.route.params.subscribe(data => {
this.id = data['id'];
this.edicion = data['id'] != null;
this.initForm();
});
}
for (const droppedFile of files) {
// Is it a file?
if (droppedFile.fileEntry.isFile) {
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
fileEntry.file((file: File) => {
// Here you can access the real file
this.nombreArchivo = file;
**//This is the test i make to find out if image is uploaded**
this.pacienteService.subirImagen(**this.nombreArchivo.name**);
// You could upload it like this:
const formData = new FormData()
formData.append('logo', file)
// Headers
/* const headers = new HttpHeaders({
'security-token': 'mytoken'
})
this.http.post('https://mybackend.com/api/upload/sanitize-and-save-
logo', formData, { headers: headers, responseType: 'blob' })
.subscribe(data => {
// Sanitized logo returned from backend
})
**/
});
} else {
// It was a directory (empty directories are added, otherwise only
files)
const fileEntry = droppedFile.fileEntry as FileSystemDirectoryEntry;
console.log(droppedFile.relativePath, fileEntry);
}
}
}
#PostMapping(value="/uploads", consumes = {
MediaType.MULTIPART_FORM_DATA_VALUE })
public ResponseEntity<?> guardarImagen(#RequestParam("adjunto")
MultipartFile file, Integer id) throws Exception{
Paciente pac = service.listarPorId(id);
//Se valida si existe el id en la base de datos
if(pac == null) {
throw new ModeloNotFoundException("ID NO ENCONTRADO " + id);
}
String fotoUsuario = file.getOriginalFilename();
Cloudinary cloudinary = new Cloudinary();
cloudinary.uploader().upload(file.getBytes(),
ObjectUtils.asMap("public_id", file.getOriginalFilename()));
Map result = cloudinary.api().resource(file.getOriginalFilename(),
ObjectUtils.emptyMap());
service.actualizarFoto(id, fotoUsuario);
return new ResponseEntity<>(result, HttpStatus.OK);
}
Basically I have this method that I got off a tutorial (My main goal is to simply return the images from the spring boot server so that I could dynamically view them in Angular)
#RestController
public class FileController {
#Autowired
ServletContext context;
#GetMapping(path = "/allImages")
public ResponseEntity<List<String>> getImages(){
List<String> images = new ArrayList<String>();
String filesPath = context.getRealPath("/images");
File fileFolder = new File(filesPath);
if(fileFolder!=null) {
for(final File file : fileFolder.listFiles()) {
if(!file.isDirectory()) {
String encodeBase64 = null;
try {
String extention = FilenameUtils.getExtension(file.getName());
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
encodeBase64 = Base64.getEncoder().encodeToString(bytes);
images.add("data:image/"+extention+";base64,"+encodeBase64);
fileInputStream.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
return new ResponseEntity<List<String>>(HttpStatus.OK);
}
With the current code, when I try to return the files, I get:
java.lang.NullPointerException: Cannot read the array length because the return value of "java.io.File.listFiles()" is null
I've been searching around and noticed that people recommend using java.nio.file instead but I'm a little lost on how would I implement this here. Any help is appreciated.
Example with nio:
public List<String> readImages() throws IOException {
return Files.list(Path.of("/images"))
.filter(Files::isRegularFile)
.map(this::encode)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private String encode(Path file) {
try {
String extension = FilenameUtils.getExtension(file.getFileName().toString());
String encodeBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(file));
return "data:image/"+extension+";base64,"+encodeBase64;
} catch (Exception e) {
return null;
}
}
First get a Path to your folder:
Path folderPath = Paths.get(filesPath);
If your Path points to a directory, you can get a Stream<Path> of its contents using Files.list:
if (Files.isDirectory(folderPath)) {
List<Path> files = Files.list(folderPath)
.filter(path -> !Files.isDirectory(path))
.collect(Collectors.toList());
// Do something with the files.
}
It doesn't look like you are using the FileInputStream for anything, so you shouldn't need to translate that part. To get the file extension of your path, you probably need to convert the Path to a string, and extract the extension yourself.
I solved this issue with this code:
#Autowired
ServletContext context;
#GetMapping(path = "/allImages")
public List<String> readImages() throws IOException {
return Files.list(Paths.get(context.getRealPath("/images")))
.filter(Files::isRegularFile)
.map(this::encode)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private String encode(Path file) {
try {
String extension = FilenameUtils.getExtension(file.getFileName().toString());
String encodeBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(file));
return "data:image/"+extension+";base64,"+encodeBase64;
} catch (Exception e) {
return null;
}
}
Thank you to everyone who helped.
I am learning Spring MVC online. As part of my course, I have to develop a Cloud Video Service. Specifications are mentioned here.
https://github.com/juleswhite/mobile-cloud-asgn1
Below is my controller class.
#Controller
public class VideosController {
private final AtomicLong currentId = new AtomicLong(1L);
//A Map to hold incoming Video meta data
private HashMap<Long, Video> videoMap = new HashMap<Long, Video>();
//Receives GET requests to /video and returns the current list
// list of videos in memory
#RequestMapping(value = "/video", method = RequestMethod.GET)
public #ResponseBody List<Video> getVideoList() throws IOException{
List<Video> resultList = new ArrayList<Video>();
for(Long id : videoMap.keySet()) {
resultList.add(videoMap.get(id));
}
return resultList;
}
//Receives POST requests to /video and adds the video object
//created from request data to the Map
#RequestMapping(value = "/video", method = RequestMethod.POST)
public #ResponseBody() Video addVideoMetadata(#RequestBody Video data)
{
//create a Video object
Video video = Video.create().withContentType(data.getContentType())
.withDuration(data.getDuration())
.withSubject(data.getSubject())
.withTitle(data.getTitle()).build();
//set the id for the video
long videoId = currentId.incrementAndGet();
video.setId(videoId);
//set the URL for this Video
String videoURL = getDataUrl(videoId);
video.setDataUrl(videoURL);
//save the Video metadata object to map
Video v = save(video);
return v;
}
// Receives POST requests to /video/{id}/data e.g. /videoa/2/data
// uploads the video file sent as MultipartFile
// and writes it to the disc
#RequestMapping(value = "/video/{id}/data", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<VideoStatus> uploadVideo
(#RequestParam("data") MultipartFile data,
#PathVariable("id") long id,
HttpServletResponse response
) throws IOException
{
// if video with id not present
if(!videoMap.containsKey(id)) {
System.out.println(" this id not present");
return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
//return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
}
InputStream in = null;
try {
//read the input stream
in = data.getInputStream();
}
catch(IOException ie){
System.out.println("Exception reading inputstream");
}
finally {
in.close();
}
//get the video
Video v = videoMap.get(id);
//write it to disk
VideoFileManager.get().saveVideoData(v, in);
VideoStatus vs = new VideoStatus(VideoStatus.VideoState.READY);
return new ResponseEntity<>(vs, HttpStatus.OK);
//response.setStatus(200);
//return new ResponseEntity<>(vs, HttpStatus.OK);
}
//Reads GET request to /vide/{id}/data and returns the video
//binary data as output stream
#RequestMapping(value = "/video/{id}/data", method = RequestMethod.GET)
public #ResponseBody ResponseEntity<OutputStream> getBinaryData(
#PathVariable("id") long videoId,
HttpServletResponse response) throws IOException {
//if id is incorrect
if(!videoMap.containsKey(videoId)) {
return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
}
//get the video from Map
Video outVideo = videoMap.get(videoId);
VideoFileManager vm = VideoFileManager.get();
//write the binary data to OutputStream
OutputStream os = response.getOutputStream();
vm.copyVideoData(outVideo, os);
return new ResponseEntity<>(os, HttpStatus.OK);
}
//save incoming video metadata to a Map
public Video save(Video v) {
checkAndSetId(v);
if(!videoMap.containsKey(v.getId())) {
videoMap.put(v.getId(), v);
}
return v;
}
//helper method to generate url for video
private String getDataUrl(long videoId){
String url = getUrlBaseForLocalServer() + "/video/" + videoId + "/data";
return url;
}
private String getUrlBaseForLocalServer() {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String base =
"http://"+request.getServerName()
+ ((request.getServerPort() != 80) ? ":"+request.getServerPort() : "");
return base;
}
private void checkAndSetId(Video entity) {
if(entity.getId() == 0){
entity.setId(currentId.incrementAndGet());
}
}
}
Now, I pass all the tests in AutoGradingTest.java Unit code but not the testAddVideoData(). It gives a Socket Time out error, followed by Infinite recursion error, pointing to line number 159 in the AutoGradingTest.java
Logically, my code seems to be fine. Lot of other learners are facing problem with thirstiest case too but there is no help from the course instructors.
Can somebody please help me here? Thanks a lot.
I am trying to store a file from user, using Java Spring boot and make a preview immediately after image upload. But now I get a 404 error on the console and when I refresh the page, the image shows up!
I tried to solve the problem by adding sleep or delay in the thread. Did not work. Here is some part of controller and service file:
public Resource getIllustrationAsResource(long id) throws MalformedURLException {
return new FileUrlResource(uploadLocation + id + ILLUSTRATION_FILE_ENDING);
}
public PostResult addIllustration(MultipartFile file) throws IOException {
Illustration illustration = getIllustrationMetadata(file);
long id = repo.insertIllustration(illustration);
storeFile(file, id);
return new PostResult(id);
}
private void storeFile(MultipartFile file, long id) throws IOException {
Path path = Paths.get(uploadLocation + id + ILLUSTRATION_FILE_ENDING);
System.out.println("storeFile path: " + path);
File uploadFile = new File(uploadLocation);
uploadFile.getParentFile().mkdirs();
try (InputStream inputStream = file.getInputStream()) {
Files.copy(inputStream, path);
}
}
Controller:
#GetMapping("/illustrations/{id}/image")
public ResponseEntity < Resource > getImageContent(#PathVariable("id") long id)
throws MalformedURLException {
Illustration illustrationInfo = service.getOneIllustration(id);
Resource body = service.getIllustrationAsResource(id);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(illustrationInfo.getMime()));
return new ResponseEntity < > (body, headers, HttpStatus.OK);
}
#PostMapping("/illustrations")
public PostResult postOneIllustration(#RequestParam("file") MultipartFile image)
throws IOException {
ProjectId project = projectService.getCurrentProject();
if (project == null) {
throw new EntityMissingException();
}
if (!authorizationService.loggedInUserCanCreateObjectsInProject(project)) {
throw new EntityMissingException();
}
return service.addIllustration(image);
}
Frontend:
postFile: async function(data) {
//console.log("here")
try {
let fetchPromise = catchReject(
fetch(`${window.contextPath}/illustrations`, {
method: 'POST',
body: data
})
)
const response = await fetchPromise
validateHttpOkStatus(response)
return response.json()
} catch (e) {
console.log('in postFile')
console.log(e)
// store.dispatch(addGlobalError(e))
throw e
}
},
How to pass InputStream to createParcel() method using Java REST client? How to call POST request using POSTMAN?
#POST
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.TEXT_PLAIN)
public int createParcel(InputStream is) {
int awbNo = 0;
try {
ParcelInfo parcelInfo = null;
parcelInfo = buildParcelInfo(is);
awbNo = index.incrementAndGet();
parcelInfo.setAwbNo(awbNo);
parcelInfo.setStatus("new");
parcelDataMap.put(awbNo, parcelInfo);
} catch(Exception ex) {
logger.error("Getting some exception for creating parcel : "+ex.getMessage(), ex);
}
return awbNo;
}
#GET
#Produces(MediaType.APPLICATION_XML)
public StreamingOutput getParcelInfo(#QueryParam("awbNo") int awbNo) {
ParcelInfo parcelInfo = null;
String xml = null;
parcelInfo = parcelDataMap.get(awbNo);
if (parcelInfo != null) {
xml = convert(parcelInfo);
}
return new ParcelInfoWriter(xml);
}
Because you are not consuming structured data but rather a raw InputStream, you first remove the #Consumes annotation; so your resource method should be:
#POST
#Produces(MediaType.TEXT_PLAIN)
public int createParcel(InputStream is) {
int awbNo = 0;
try {
ParcelInfo parcelInfo = null;
parcelInfo = buildParcelInfo(is);
// the rest of your code here
}catch(Exception ex) {
// catch specific exception instead of `Exception`
}
return awbNo;
}
Now use Postman to call your resource. The content body of your request can be any conent (in my example it is XML but you can send anything you like). Look at the screenshot below how to set the request correctly:
Execuse me for the drawing :-)