How to display uploaded images URL in browser - java

I am new for Multi-part in Spring Boot and I copied below code from internet for uploading files and its working fine. My requirement is after storing my files i just want to display them whenever I paste image URL in browser but using below code its getting download whenever I paste image URL.
How can I just show uploaded files instead of download?
controller
#RestController
public class FileController {
private static final Logger logger = LoggerFactory.getLogger(FileController.class);
#Autowired
private FileStorageService fileStorageService;
#PostMapping("/uploadFile")
public UploadFileResponse uploadFile(#RequestParam("file") MultipartFile file) {
String fileName = fileStorageService.storeFile(file);
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/downloadFile/")
.path(fileName)
.toUriString();
return new UploadFileResponse(fileName, fileDownloadUri,
file.getContentType(), file.getSize());
}
#GetMapping("/downloadFile/{fileName:.+}")
public ResponseEntity<Resource> downloadFile(#PathVariable String fileName, HttpServletRequest request) {
// Load file as Resource
Resource resource = fileStorageService.loadFileAsResource(fileName);
// Try to determine file's content type
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
logger.info("Could not determine file type.");
}
// Fallback to the default content type if type could not be determined
if(contentType == null) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
}
Service
#Service
public class FileStorageService {
private final Path fileStorageLocation;
#Autowired
public FileStorageService(FileStorageProperties fileStorageProperties) {
this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
.toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
public String storeFile(MultipartFile file) {
// Normalize file name
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
// Check if the file's name contains invalid characters
if(fileName.contains("..")) {
throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
}
// Copy file to the target location (Replacing existing file with the same name)
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return fileName;
} catch (IOException ex) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
public Resource loadFileAsResource(String fileName) {
try {
Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if(resource.exists()) {
return resource;
} else {
throw new MyFileNotFoundException("File not found " + fileName);
}
} catch (MalformedURLException ex) {
throw new MyFileNotFoundException("File not found " + fileName, ex);
}
}
}

Remove the line:
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
The Content-Disposition HTTP header usually triggers the download behavior. So you don't want to use it.

Related

Broken Image when uploading using Rest Controller Multipart File

When i try to upload image in my RestController using MultipartFile, sometimes it creates a broken image (which doesn't open, just has some trashes inside file). It happens when i try to send (through Postman) images fast.
Here is my Controller:
#PostMapping("/upload/photo")
public ResponseEntity<ServerResponse> uploadPhoto(#RequestParam MultipartFile file, HttpServletRequest httpServletRequest) {
UserAccount userAccount = getPrincipal();
String localAddress = "http://" + getServerUrl(httpServletRequest);
ServerResponse response = userAccountService.addPhoto(userAccount, file, localAddress);
return getResponseEntity(response);
}
And my Service:
#Override
public ServerResponse<String> addPhoto(UserAccount userAccount, MultipartFile file, String localAddress) {
String uploadFilePath = uploadFile(file);
if(uploadFilePath.isEmpty()) {
return new ServerResponse<>(ResponseStatus.BAD_REQUEST, "Please select a file to upload", "");
}
final String PHOTO_URL = localAddress + "/" + uploadFilePath;
userAccount.setPhoto(PHOTO_URL);
userAccountRepository.save(userAccount);
return new ServerResponse<>(ResponseStatus.OK, null, PHOTO_URL);
}
private String uploadFile(MultipartFile file) {
if (file.isEmpty()) {
return "";
}
final String UPLOADED_FOLDER = "photos";
String uniqueName = generateRandomString();
String filePath = UPLOADED_FOLDER + "/" + uniqueName + file.getOriginalFilename();
new File(UPLOADED_FOLDER).mkdirs();
try {
byte[] bytes = file.getBytes();
Path path = Paths.get(filePath);
if (Files.exists(path)){
uniqueName = generateRandomString();
filePath = UPLOADED_FOLDER + "/" + uniqueName + file.getOriginalFilename();
path = Paths.get(filePath);
}
Files.write(path, bytes);
} catch (IOException e) {
e.printStackTrace();
}
return filePath;
}
I also tried to read multipart file as InputStream, but didin't help.
try (InputStream inputStream = file.getInputStream()) {
Files.copy(inputStream, path,
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
I think the problem is, when i try to send couple images at the pretty same time it just can't handle that?

Download file / installer jar which is part of war from tomcat server (window and linux)

I was facing problem to download installer jar from war deployed on tomcat server on window machine. The code was working on linux machine but not on window machine.
public Response downloadPOST(#Context HttpServletRequest request) {
long length = 0;
byte[] data;
try {
WebApplicationContext context = (WebApplicationContext) WebApplicationContextProvider
.getApplicationContext();
String sPath = context.getServletContext()
.getResource("/installer/installer-" + Version.VERSION + ".jar").getPath();
java.nio.file.Path path = Paths.get(sPath);
data = Files.readAllBytes(path);
length = data.length;
} catch (Exception e) {
logger.error( e);
throw new WebApplicationException("File Not Found !!");
}
StreamingOutput fileStream = new StreamingOutput() {
#Override
public void write(java.io.OutputStream output) throws IOException, WebApplicationException {
try {
output.write(data);
output.flush();
} catch (Exception e) {
logger.error( e);
throw new WebApplicationException("File Not Found !!");
}
}
};
return Response.ok(fileStream, MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition",
"attachment; filename = installer-" + Version.VERSION + ".jar")
.header("Content-Length", String.valueOf(length)).build();
}
The above code was throwing NoSuchFileException due to special character and prefix '/' in file path on window machine.
java.nio.file.NoSuchFileException: /C:\Program%20Files\Apache%20Software%20Foundation\Tomcat%208.0\webapps\ROOT\installer\installer-x.x.x.jar
I have fixed this issue by using UrlDecoder and using regular expression to remove prefix '/' from url.
The code which is working for window and linux machine
public Response downloadPOST(#Context HttpServletRequest request) {
long length = 0;
byte[] data;
try {
WebApplicationContext context = (WebApplicationContext) WebApplicationContextProvider
.getApplicationContext();
String sPath = context.getServletContext()
.getResource("/installer/installer-" + AgentVersion.STRING_VERSION + ".jar").getPath();
sPath = URLDecoder.decode(sPath, "utf-8");
// get the right path on Windows or Linux on any drive letter
// window : if the beginning of the string is a slash, then a
// character, then a colon and another slash, replace it with the
// character, the colon, and the slash (leaving the leading slash
// off).
sPath = sPath.replaceFirst("^/(.:/)", "$1");
java.nio.file.Path path = Paths.get(sPath);
data = Files.readAllBytes(path);
length = data.length;
} catch (Exception e) {
logger.error(e.getClass().getSimpleName() + " at " + request.getRequestURI(), e);
throw new WebApplicationException("File Not Found !!");
}
StreamingOutput fileStream = new StreamingOutput() {
#Override
public void write(java.io.OutputStream output) throws IOException, WebApplicationException {
try {
output.write(data);
output.flush();
} catch (Exception e) {
logger.error(e.getClass().getSimpleName() + " at " + request.getRequestURI(), e);
throw new WebApplicationException("File Not Found !!");
}
}
};
return Response.ok(fileStream, MediaType.APPLICATION_OCTET_STREAM)
.header("content-disposition",
"attachment; filename = installer-" + Version.VERSION + ".jar")
.header("Content-Length", String.valueOf(length)).build();
}

How to create MultipartFile with location file (path)

I have location file (C:\fakepath\Code.txt) . I want to create MultipartFile with this location. My Code:
public void fileUpload(String locationFile) {
Path path = Paths.get(locationFile);
String name = "Code.txt";
String originalFileName = "Code.txt";
String contentType = "text/plain";
byte[] content = null;
try {
content = Files.readAllBytes(path);
} catch (final IOException e) {
}
MultipartFile file = new MockMultipartFile(name, originalFileName, contentType, content);
try {
// Get the file and save it somewhere
byte[] bytes = file.getBytes();
Path paths = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
Files.write(paths, bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
Also in this code I need type my file name it's not correct for my opinion. How to create MultipartFile and save somewhere? with location
In Windows you need double slashes "C://fakepath//Code.txt"

How to clean up temporary file after response in JAX-RS REST Service?

I am returning a temporary file from my JAX-RS REST Service like below:
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // create a temporary file
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
}
What is the correct way of removing this temporary file after the response has been processed? Is the JAX-RS implementation (like Jersey) supposed to do this automatically?
You can pass an instance of StreamingOutput that copies the content of the source file to the client output and eventually deletes the file.
final Path path = getTheFile().toPath();
final StreamingOutput output = o -> {
final long copied = Files.copy(path, o);
final boolean deleted = Files.deleteIfExists(path);
};
return Response.ok(output).build();
final File file = getTheFile();
return Response.ok((StreamingOutput) output -> {
final long copied = Files.copy(file.toPath(), output);
final boolean deleted = file.delete();
}).build();
The example on https://dzone.com/articles/jax-rs-streaming-response looks more helpful than the brief reply from Jin Kwon.
Here is an example:
public Response getDocumentForMachine(#PathParam("custno") String custno, #PathParam("machineno") String machineno,
#PathParam("documentno") String documentno, #QueryParam("language") #DefaultValue("de") String language)
throws Exception {
log.info(String.format("Get document. mnr=%s, docno=%s, lang=%s", machineno, documentno, language));
File file = new DocFileHelper(request).getDocumentForMachine(machineno, documentno, language);
if (file == null) {
log.error("File not found");
return Response .status(404)
.build();
}
StreamingOutput stream = new StreamingOutput() {
#Override
public void write(OutputStream out) throws IOException, WebApplicationException {
log.info("Stream file: " + file);
try (FileInputStream inp = new FileInputStream(file)) {
byte[] buff = new byte[1024];
int len = 0;
while ((len = inp.read(buff)) >= 0) {
out.write(buff, 0, len);
}
out.flush();
} catch (Exception e) {
log.log(Level.ERROR, "Stream file failed", e);
throw new IOException("Stream error: " + e.getMessage());
} finally {
log.info("Remove stream file: " + file);
file.delete();
}
}
};
return Response .ok(stream)
.build();
}

File transfer is canceled during REST download

I have a little problem when I try to download a file with rest.
Here is my function :
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
#Path("{directory: (([^/]+[/])+)[^/]+}")
public Response getFile(#PathParam("directory") String directory)
{
Response responseFile = null;
try
{
/*String tmpFileName = "REST_FTP_TMPFile_"+ Math.random();
tmpFileName = tmpFileName.replace(".", "");
File tmpFile = new File(tmpFileName);
tmpFile.createNewFile();
//*/
String filename = directory.substring(directory.lastIndexOf("/")+1, directory.length());
File tmpFile = File.createTempFile("REST_FTP_TMPFile_", null);
directory = StringEscapeUtils.unescapeHtml4(directory);
this.client.getFile(directory, tmpFile);
System.out.println("size : " + tmpFile.length());
responseFile = Response.ok(tmpFile, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-length", tmpFile.length())
.header("Content-Disposition","attachment; filename="+filename+"")
.build();
//A voir quand on peut le supprimer...
//tmpFile.delete();
}
catch (IOException ex)
{
Logger.getLogger(GetResource.class.getName()).log(Level.SEVERE, null, ex);
}
return responseFile;
}
The function getFile of client use the libapache method :
public boolean getFile(String pathname, File file) throws IOException
{
OutputStream output;
output = new FileOutputStream(file);
System.out.println("Wanted pathname : "+pathname);
boolean status = this.client.retrieveFile("/"+pathname, output);
if(status)
{
output.close();
return status;
}
else
{
output.close();
throw new IOException("Cannot retrieve the file : " + pathname);
}
}
When I try to download my web browser says that the download is canceled :
I really don't know what I did wrong and nothing on the web helped me out so far (it's been 2 hours..)
I found what the problem was, the FTP transfer is supposed to be in binary mode..

Categories