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
}
},
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);
}
I'm trying to find a way to download file from api without window.open().
I'd like to get instant download when calling the api.
Currently downloading .xls file generated by a rest api using window.open()
API Endpoint
#GetMapping("/applications/export")
#Timed
public ResponseEntity<byte[]> exportApplicationsList() {
log.debug("REST request to export applications list");
byte[] result = applicationService.generateApplicationsListAsExcel();
if (result == null) {
return ResponseEntity.status(500).build();
}
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd_MM_yyyy_HH_mm"));
return ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=liste_applications_" + date + ".xls")
.contentLength(result.length)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(result);
}
Service
/**
* Generate xls file from applications list.
*
* #param applications list of applications
*/
public byte[] generateApplicationsListAsExcel() {
log.info("Génération fichier xls de la liste des applications");
List<Application> applications = applicationRepository.findAll();
Collections.sort(applications);
try (InputStream is = new FileInputStream(ResourceUtils.getFile("classpath:jxls-templates/liste_applications_template.xls"))) {
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
Context context = new Context();
context.putVar("applications", applications);
JxlsHelper.getInstance().processTemplate(is, os, context);
return os.toByteArray();
} catch (IOException e) {
log.error(e.toString());
}
} catch (IOException e) {
log.error(e.toString());
}
return null;
}
Invocation
exportApplicationsList(): void {
window.open('/api/applications/export');
}
You can return file as blob as response from backend and then use file-saver to download the file
this.http.get(`/api/applications/export`, params, { responseType: 'blob' })
.subscribe((resp: any) => {
saveAs(resp, `filename}.xlsx`)
});
Quick solution : window.location.href = url;
I used this file-saver, I think it will fulfill your needs.
this.filesService.getDownloadFile(id).subscribe(
data => {
importedSaveAs(data, name);
},
err => {
console.error(err);
});
For the backend:
#GetMapping("download-file/{id}")
public ResponseEntity<?> downloadFile(#PathVariable(value = "id") Long id) {
final Optional<FileEntity> file = fileRepository.findById(id);
if (!file.isPresent()) {
return ResponseEntity.badRequest().body(getErrorResponse("File not found"));
}
ByteArrayOutputStream downloadInputStream = amazonClient.downloadFile(file.get().getLink());
return ResponseEntity.ok()
.contentType(contentType(file.get().getName()))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.get().getName() + "\"")
.body(downloadInputStream.toByteArray());
}
The error happened when i upload a 115KB image file to server.(the most answer of stackoverflow is about download the file.I do not know if it is the same to those)
the error information is below:
onFailure : java.net.ProtocolException: unexpected end of stream
Relevant Code:
public void upLoadImageFile(String uploadUrl, File file, Map<String, String> maps, final HWUploadListener listener) {
final CallbackHandler handler = new CallbackHandler(listener);
try {
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
if (maps == null) {
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"image\";filename=\"file.jpg\""),
RequestBody.create(MediaType.parse("image/jpeg"), file)).build();
} else {
for (String key : maps.keySet()) {
builder.addFormDataPart(key, maps.get(key));
}
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"image\";filename=" + file.getName()), RequestBody.create(MediaType.parse("image/jpeg"), file)
);
}
RequestBody body = builder.build();
final Request request = new Request.Builder().url(uploadUrl).post(body).build();
final Call call = mOkHttpClient.newBuilder().writeTimeout(50, TimeUnit.SECONDS).build().newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
UtilUtils1.log("HuowuSdk", "onFailure :" + e.toString());
handler.uploadFailure(e.toString());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String result = response.body().string();
handler.uploadSuccess(result);
} else {
handler.uploadFailure(response.message());
}
}
});
} catch (Exception e) {
UtilUtils1.log("HuowuSdk", e.toString());
handler.uploadError(e.toString());
}
}
Appreciate your answer!!
Here in this line below you have to increase write timeout because while uploading your write timeout expires that may be the reason so in below line increase writeTimeout limit:
final Call call = mOkHttpClient.newBuilder().writeTimeout(50, TimeUnit.SECONDS).build().newCall(request);
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();
}
I used a jersey server and I want that a endpoint redirect to the download of a file depending on parameters.
I have difficulties with the function below :
#GET
#Path("/get/{id}/{chunk}")
public Response getDescription(#PathParam("id") String id, #PathParam("chunk") String chunk) {
{
StreamingOutput fileStream = new StreamingOutput()
{
#Override
public void write(java.io.OutputStream output, String id) throws IOException, WebApplicationException
{
try
{
if (Objects.equals(chunk, new String("init"))) {
java.nio.file.Path path = Paths.get("src/main/uploads/example/frame_init.pdf");
}
else {
java.nio.file.Path path = Paths.get("src/main/uploads/example/"+ id +".pdf");
}
byte[] data = Files.readAllBytes(path);
output.write(data);
output.flush();
}
catch (Exception e)
{
throw new WebApplicationException("File Not Found !!");
}
}
};
return Response
.ok(fileStream, MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition","attachment; filename = myfile.pdf")
.build();
}
I have a problem with passing parameters to the function write. I have my parameters id and chunk by the endpoint but I can't use it in the write method because it implements StreamingOutput().
How I can handle it ? Thank you
For java, final keyword should solve your problem.
As updated code;
#GET
#Path("/get/{id}/{chunk}")
public Response getDescription(#PathParam("id") final String id, #PathParam("chunk") final String chunk) {
{
StreamingOutput fileStream = new StreamingOutput()
{
#Override
public void write(java.io.OutputStream output, String id2) throws IOException, WebApplicationException
{
try
{
if (Objects.equals(chunk, new String("init"))) {
java.nio.file.Path path = Paths.get("src/main/uploads/example/frame_init.pdf");
}
else {
java.nio.file.Path path = Paths.get("src/main/uploads/example/"+ id2 +".pdf");
}
byte[] data = Files.readAllBytes(path);
output.write(data);
output.flush();
}
catch (Exception e)
{
throw new WebApplicationException("File Not Found !!");
}
}
};
return Response
.ok(fileStream, MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition","attachment; filename = myfile.pdf")
.build();
}