I want to download files using SpringBoot - spring-boot

An attempt was made to implement file downloads through the SpringBoot MVC structure. There is no error, it says it has run normally, but the download does not proceed.
All information about the file is entered correctly, and also the path and name of the file are entered correctly.
I'd like to know why the download doesn't proceed even though there's no error.
#RestController
public class Controller {
#PostMapping("/fileDownload")
public void fileDownload(#RequestBody BoardFileDTO dto,HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException {
//File contains all stored paths, names, and extensions
Path fileNamePath = Paths.get(Directory + dto.getFile_save_name()).toAbsolutePath();
String filename = dto.getFile_save_name(); //The name of the saved file
String downname = dto.getFile_name(); //The name of the file to be saved
if (filename == null || "".equals(filename)) {
filename = downname;
}
try {
String browser = request.getHeader("User-Agent");
//File Encoding
if (browser.contains("MSIE") || browser.contains("Trident")
|| browser.contains("Chrome")) {
filename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+",
"%20");
} else {
filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
}
} catch (UnsupportedEncodingException ex) {
System.out.println("UnsupportedEncodingException");
}
System.out.println(fileNamePath);
File file1 = new File(fileNamePath.toString());
if (!file1.exists()) {
return ;
}
// Specifying a File
response.setContentType("application/octer-stream");
response.setHeader("Content-Transfer-Encoding", "binary;");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
try {
OutputStream os = response.getOutputStream();
FileInputStream fis = new FileInputStream(fileNamePath.toString());
int ncount = 0;
byte[] bytes = new byte[512];
while ((ncount = fis.read(bytes)) != -1 ) {
os.write(bytes, 0, ncount);
}
fis.close();
os.close();
} catch (FileNotFoundException ex) {
System.out.println("FileNotFoundException");
} catch (IOException ex) {
System.out.println("IOException");
}
}
}

Your code is a bit convoluted imho. A couple of issues I see with your code
Using Path.toString to convert to a File, use the proper factory methods instead or use java.nio.Files to check the existence.
Your content-type is wrong application/octer-stream isn't a known content-type (you probably want application/octet-stream.
Copying from a Path or File is better done with either the StreamUtils from Spring or the java.nio.Files class (if you already have a Path use that).
#PostMapping("/fileDownload")
public void fileDownload(#RequestBody BoardFileDTO dto, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
//File contains all stored paths, names, and extensions
Path fileNamePath = Paths.get(Directory, dto.getFile_save_name()).toAbsolutePath();
if (!Files.exists(fileNamePath)) {
return;
}
String filename = determineFilename(dto, request);
// Specifying a File
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Transfer-Encoding", "binary;");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
try {
Files.copy(fileNamePath, response.getOutputStream());
} catch (IOException ex) {
System.out.println("IOException");
}
}
private static String determineFilename(BoardFileDTO dto, HttpServletRequest request) {
String filename = dto.getFile_save_name(); //The name of the saved file
if (filename == null || "".equals(filename)) {
filename = dto.getFile_name();
}
String browser = request.getHeader("User-Agent");
//File Encoding
if (browser.contains("MSIE") || browser.contains("Trident") || browser.contains("Chrome")) {
filename = URLEncoder.encode(filename, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
} else {
filename = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}
return filename;
}
It would write it something like that. As you have a path use the java.nio.Files to check for existence and copying. Use constants for mediatypes and charsets.
Your error handling is quite basic (I would say non-existing and at least not proper) as the processing just stops and returns an empty 200 to the client. No information what so ever.
I took the liberty to factor out the logic to determine the filename, which should make your code more readable.

Related

How to use postman for testing get request given below?

I want to create an android app to perform file operations in google drive which uses Spring boot as backend. So I had searched so many times in google and finally I got this one. But they didn't mentioned about the working. If anyone knows please help me. And please suggest some good tutorial to perform file operations in google drive using Spring boot rest api.
Get Request to create a directory in Google Drive
#GetMapping("/directory/create")
public ResponseEntity<String> createDirectory(#RequestParam String path) throws Exception {
String parentId = fileManager.getFolderId(path);
return ResponseEntity.ok("parentId: "+parentId);
}
getFolderId Function
public String getFolderId(String path) throws Exception {
String parentId = null;
String[] folderNames = path.split("/");
Drive driveInstance = googleDriveManager.getInstance();
for (String name : folderNames) {
parentId = findOrCreateFolder(parentId, name, driveInstance);
}
return parentId;
}
findOrCreateFolder Function to create if given folder does not exist in google drive
private String findOrCreateFolder(String parentId, String folderName, Drive driveInstance) throws Exception {
String folderId = searchFolderId(parentId, folderName, driveInstance);
// Folder already exists, so return id
if (folderId != null) {
return folderId;
}
//Folder dont exists, create it and return folderId
File fileMetadata = new File();
fileMetadata.setMimeType("application/vnd.google-apps.folder");
fileMetadata.setName(folderName);
if (parentId != null) {
fileMetadata.setParents(Collections.singletonList(parentId));
}
return driveInstance.files().create(fileMetadata)
.setFields("id")
.execute()
.getId();
}
Post request to upload file to google drive
#PostMapping(value = "/upload",
consumes = {MediaType.MULTIPART_FORM_DATA_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE} )
public ResponseEntity<String> uploadSingleFileExample4(#RequestBody MultipartFile file,#RequestParam(required = false) String path) {
logger.info("Request contains, File: " + file.getOriginalFilename());
String fileId = fileManager.uploadFile(file, path);
if(fileId == null){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
return ResponseEntity.ok("Success, FileId: "+ fileId);
}
Upload function to upload file to google drive
public String uploadFile(MultipartFile file, String filePath) {
try {
String folderId = getFolderId(filePath);
if (file != null) {
File fileMetadata = new File();
fileMetadata.setParents(Collections.singletonList(folderId));
fileMetadata.setName(file.getOriginalFilename());
File uploadFile = googleDriveManager.getInstance()
.files()
.create(fileMetadata, new InputStreamContent(
file.getContentType(),
new ByteArrayInputStream(file.getBytes()))
)
.setFields("id").execute();
return uploadFile.getId();
}
} catch (Exception e) {
System.out.print("Error: "+e);
}
return null;
}
Reference
https://technicalsand.com/file-operations-in-google-drive-api-with-spring-boot/
To test the above get request in postman.
Assume you are running on localhost:8080 then request will be -
localhost:8080?path="directory_name"
Testing GET request in Postman: Image
If you are running in local,
http://{host}:{port}/{endpoint}
http://localhost:8080/directory/create

how to upload an image using servlet to an absolute path

I want to upload a file to my project folder. My code is as follows:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
File savedFile;
String destination;
List<FileItem> items = null;
try {
items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (FileItem item : items) {
if (item.isFormField()) {
// Process regular form field (input type="text|radio|checkbox|etc", select, etc).
} else {
// Process form file field (input type="file").
String fieldName = item.getFieldName();
String fileName = FilenameUtils.getName(item.getName());
InputStream fileContent = item.getInputStream();
String userName = (String) session.getAttribute("newUser");
destination = getServletConfig().getServletContext().getContextPath() + "\\" + userName + ".jpeg";
savedFile = new File(destination);
//Check if file exists
if(!savedFile.exists())
savedFile.createNewFile();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(savedFile));
byte[] buffer = new byte[1024];
int len;
//Read from file and write to new file destination
while((len = fileContent.read(buffer)) >= 0) {
bos.write(buffer, 0, len);
}
//Closing the streams
fileContent.close();
bos.close();
}
}
}
When I run the jsp file and browse and select the required image and submit the form, the servlet runs but it throws IOException. The exception is throws by the line where I create a new path using savedFile.createNewFile(). Before I used that code, it threw another FileNotFoundException. I am not sure if the path that I have provided is correct.
Try to use getRealPath() method.
String fileName="/" + userName + ".jpeg";
destination = getServletContext().getRealPath(fileName);
savedFile = new File(destination);

how to calculate the file size in C#

In my asp mvc 3 application, I have an action which allows the user to download a given file.
Here is the code :
public FilePathResult DownloadFile(string fileName)
{
try
{
string uploadsDocumentPath = System.Configuration.ConfigurationManager.AppSettings["uploadsDocumentPath"].ToString();
string ext = Path.GetExtension(fileName).ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext); // henter info fra windows registry
if (regKey != null && regKey.GetValue("Content Type") != null)
{
mimeType = regKey.GetValue("Content Type").ToString();
}
return File(uploadsDocumentPath + fileName, mimeType, fileName);
}
catch (Exception)
{
throw;
}
}
I want to be able to allow only files with size less than 150MB to be downloaded. But I can't find how to calculate this type of file's size.
Any ideas ?
I guess this should work:
FileInfo file = new FileInfo(uploadsDocumentPath + fileName);
if(file.Length > 157286400)
{
// Return error here.
}

MVC 3 The process cannot access the file because it is being used by another process

I upload a file in my MVC 3 project.
[HttpPost]
public ActionResult MyUpload(HttpPostedFileBase file)
{
string filePath = string.Empty;
string path = "C:\\";
string filePath = string.Empty;
try
{
if (file != null && file.ContentLength > 0)
{
filePath = path + file.FileName;
file.SaveAs(filePath);
file.InputStream.Dispose();
GC.Collect();
// other operations, where can occur an exception
// (because the uploaded file can have a bad content etc.)
}
}
catch (Exception e)
{
if (file.InputStream != null)
file.InputStream.Dispose();
GC.Collect();
if (!string.IsNullOrEmpty(filePath))
{
if (System.IO.File.Exists(filePath))
System.IO.File.Delete(filePath); //here is the error
}
}
}
in that code, if an exception occured after I saved the file I can't delete it (also I cann't upload it again) because I get the error
The process cannot access the file
'[filePath]' because it is being used by another process.
What's wrong with that code ?
edit
I had to change the file.InputStream.Dispose(); to
file.InputStream.Close();
file.InputStream.Dispose();
file.InputStream = null;
And, now it's working fine.
Instead of checking if the file.InputStream is not null inside the catch block, you should dispose it inside the finally block, like this:
if (file != null && file.ContentLength > 0)
{
try
{
filePath = path + file.FileName;
file.SaveAs(filePath);
// other operations, where can occur an exception
// (because the uploaded file can have a bad content etc.)
}
catch (Exception e)
{
if (!string.IsNullOrEmpty(filePath))
{
if (System.IO.File.Exists(filePath))
System.IO.File.Delete(filePath); //here is the error
}
}
finally
{
file.InputStream.Close();
file.InputStream.Dispose();
GC.Collect();
}
}
By the way, the InputStream property is a read-only property. You can't set it to null.

How to make a save action that checks whether a 'save-as' has already been performed

I have researched and tried to refer back to my fileChooser.getSeletedFile() in my save as action but can not work out how to check whether or not a file has been created. Here is my attempted code so far:
Save as code(works well):
public void Save_As() {
fileChooserTest.setApproveButtonText("Save");
int actionDialog = fileChooserTest.showOpenDialog(this);
File fileName = new File(fileChooserTest.getSelectedFile() + ".txt");
try {
if (fileName == null) {
return;
}
BufferedWriter outFile = new BufferedWriter(new FileWriter(fileName));
outFile.write(this.jTextArea2.getText());//put in textfile
outFile.flush(); // redundant, done by close()
outFile.close();
} catch (IOException ex) {
}
}
"Save" code doesn't work:
private void SaveActionPerformed(java.awt.event.ActionEvent evt) {
File f = fileChooserTest.getSelectedFile();
try {
if (f.exists()) {
BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileChooserTest.getSelectedFile() + ".txt"));
bw1 = new BufferedWriter(new FileWriter(fileChooserTest.getSelectedFile() + ".txt"));
String text = ((JTextArea) jTabbedPane1.getSelectedComponent()).getText();
bw1.write(text);
bw1.close();
} else {
Save_As();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
Instead of storing an instance to the JFileChooser rather store an instance to the File (wich will be null before any save has been performed). In your SaveActionPerformed method check if the file is null. If it is null then do a Save_As and store the selected file in your file variable, if it is not null then do a normal save into the file.

Resources