I have Web Application hosted on Linux, contains page to upload .rar file and another page to download it. for upload function working fine and file uploaded successfully to server but for download it gives me below exception:
[servelt.scriptdownloadservelt] in context with path [/OSS-CPE-Tracker] threw exception
java.io.FileNotFoundException: \usr\local\apache-tomcat-8.5.31\OSS-CPE-Tracker\Zaky\QCAM.rar (No such file or directory)
I used below funcation to make upload:
String destDir = "/usr/local/apache-tomcat-8.5.31/OSS-CPE-Tracker/Zaky";
for (FileItem item : multiparts) {
if (!item.isFormField()) {
String name = new File(item.getName()).getName();
if(name.equalsIgnoreCase("QCAM.rar")) {
File destFile = new File(destDir, "QCAM.rar");
if (destFile.exists()) {
destFile.delete();
}
item.write(new File("/usr/local/apache-tomcat-8.5.31/OSS-CPE-Tracker/Zaky" + File.separator + name));
request.setAttribute("gurumessage", "File Uploaded Successfully");
}else {
request.setAttribute("gurumessage", "Kindly use the agreed name");
}
and here function for download that i face issue on it and above exception appear:
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String gurufile = "QCAM.rar\\";
String gurupath = "\\usr\\local\\apache-tomcat-8.5.31\\OSS-CPE-Tracker\\Zaky";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "attachment; filename=\""
+ gurufile + "\"");
FileInputStream fileInputStream = new FileInputStream(gurupath
+ gurufile);
int i;
while ((i = fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
out.close();
The only reason for this error is that file cannot be found under that path.
Please verify the path
String gurufile = "QCAM.rar\\";
String gurupath = "\\usr\\local\\apache-tomcat-8.5.31\\OSS-CPE-Tracker\\Zaky";
// <...>
FileInputStream fileInputStream = new FileInputStream(gurupath
+ gurufile);
In unix systems file path is resolved using forward slash / and not a backslash \.
Try changing to the same value as your upload script:
FileInputStream fileInputStream = new FileInputStream("/usr/local/apache-tomcat-8.5.31/OSS-CPE-Tracker/Zaky/QCAM.rar")
That should do
Related
I want to upload a file from a struts action. I need in that action the path for my folder:
I tried using
String contextPath = request.getContextPath();
but I'm getting java.lang.NullPointerException
Either store in Catalina which is parent folder to your project folder
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "yourfolderName");
if (!dir.exists())
dir.mkdirs();
// Create the file on server
java.util.Date date= new java.util.Date();
String Path = dir.getAbsolutePath() + File.separator + (new Timestamp(date.getTime())).toString().replace(":", "").toString().replace(".", ".").toString().replace(" ","").toString().replace("-","").toString()+".pdf";
Or make a folder in your project and store there.
if (!file.isEmpty()) {
//filter for checking file extewnsion
if(file.getContentType().equalsIgnoreCase("image/jpg") || file.getContentType().equalsIgnoreCase("image/jpeg")){
//if file is >2 MB or < 2MB
double size = file.getSize();
double kilobytes = (size / 1024);
double megabytes = (kilobytes / 1024);
if(megabytes<2){
try {
byte[] bytes = file.getBytes();
String filePath = request.getRealPath("/")+"yourFolderName\\ProfileImages\\"+SessionManagement.getUserName()+".jpg";
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(filePath)));
stream.write(bytes);
stream.close();
//console call
}
else{
model.put("error", "Please select File less than 2 MB");
return new ModelAndView("uploadPhotoTile");
}
}else{
model.put("error", "Please select JPEG File");
return new ModelAndView("uploadPhotoTile");
}
} else {
model.put("error", "Please select File");
return new ModelAndView("uploadPhotoTile");
}
I have a Spring controller with /file mapping that gets a file name from user and stream file content to user
#RequestMapping(value = "/file" , method = RequestMethod.GET)
#ResponseBody
public void getFile(#RequestParam(value = "name", required = true) String fileName,
HttpServletResponse response)
{
String fileExtension = "";
int i = fileName.lastIndexOf('.');
if (i > 0) {
fileExtension = fileName.substring(i+1);
}
// file extension for requested file must be xls
if(!fileExtension.equals("xls"))
{
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
try {
Path path = Paths.get("/tmp/" + fileName);
byte[] data = Files.readAllBytes(path);
response.setHeader("Content-Disposition", "inline; filename=" + fileName);
response.setContentType("application/vnd.ms-excel");
response.setContentLength(data.length);
try {
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(data);
outputStream.flush();
} catch (Exception e) {
}
} catch (Exception e) {
}
}
User only can download file with .xls extension in tmp folder. the problem with this code is that user can change directory and download other .xls files in other directories. for example if there is a file in this path /tmp/tmp2/ab.xls user can download the file with calling this url http://myserver.mydomain:myport/mycontext/file?name=tmp2/ab.xls that is a security hole. what is the best way for checking name that I give from user is a file name? (not directory/filename or ../filename or another dangerous path )
Path tmpPath = Paths.get("/tmp/"); //valid directory
String fileName = "foo/bar.xls"; //supplied fileName
Path filePath = tmpPath.resolve(fileName); //add fileName to path
Path fileParent = filePath.getParent(); //get parent directory
System.out.println(fileParent);
System.out.println(tmpPath.equals(fileParent)); //false because fileParent is '/tmp/foo'
'tmpPath' will be equals 'fileParent' if you supply a valid fileName like 'bar.xls'.
I think you can also simplify the extension checking: filePath.endsWith(".xls"); should be enough. And don't concatenate file paths ("/tmp/" + fileName). Paths.get("/tmp", fileName) will do that for you.
I am using org.apache.commons.net.ftp.FTPClient for retrieving files from a ftp server. It is crucial that I preserve the last modified timestamp on the file when its saved on my machine. Do anyone have a suggestion for how to solve this?
This is how I solved it:
public boolean retrieveFile(String path, String filename, long lastModified) throws IOException {
File localFile = new File(path + "/" + filename);
OutputStream outputStream = new FileOutputStream(localFile);
boolean success = client.retrieveFile(filename, outputStream);
outputStream.close();
localFile.setLastModified(lastModified);
return success;
}
I wish the Apache-team would implement this feature.
This is how you can use it:
List<FTPFile> ftpFiles = Arrays.asList(client.listFiles());
for(FTPFile file : ftpFiles) {
retrieveFile("/tmp", file.getName(), file.getTimestamp().getTime());
}
You can modify the timestamp after downloading the file.
The timestamp can be retrieved through the LIST command, or the (non standard) MDTM command.
You can see here how to do modify the time stamp: that: http://www.mkyong.com/java/how-to-change-the-file-last-modified-date-in-java/
When download list of files, like all files returned by by FTPClient.mlistDir or FTPClient.listFiles, use the timestamp returned with the listing to update timestemp of local downloaded files:
String remotePath = "/remote/path";
String localPath = "C:\\local\\path";
FTPFile[] remoteFiles = ftpClient.mlistDir(remotePath);
for (FTPFile remoteFile : remoteFiles) {
File localFile = new File(localPath + "\\" + remoteFile.getName());
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));
if (ftpClient.retrieveFile(remotePath + "/" + remoteFile.getName(), outputStream))
{
System.out.println("File " + remoteFile.getName() + " downloaded successfully.");
}
outputStream.close();
localFile.setLastModified(remoteFile.getTimestamp().getTimeInMillis());
}
When downloading a single specific file only, use FTPClient.mdtmFile to retrieve the remote file timestamp and update timestamp of the downloaded local file accordingly:
File localFile = new File("C:\\local\\path\\file.zip");
FTPFile remoteFile = ftpClient.mdtmFile("/remote/path/file.zip");
if (remoteFile != null)
{
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));
if (ftpClient.retrieveFile(remoteFile.getName(), outputStream))
{
System.out.println("File downloaded successfully.");
}
outputStream.close();
localFile.setLastModified(remoteFile.getTimestamp().getTimeInMillis());
}
I am hosting a website on Tomcat server. The application uses Struts 1.1 and Spring for all its operations. I have a page that is used for uploading files to the server.
When user uploads any file it is successfully uploaded but gives a 404 error when tried to retrieve. I checked the file using SSH login, the uploaded file is present in that location. I am scratching my head over this problem from past 4 days but no solution. Its works properly without any problems in my local machine. The problem in there in the deployment.
An Important note: From SSH login, If i try to move that file to some other location and then place it back to its original location, i am able to retrieve the file..!!! I don't know why but I can't do this for every file uploaded by the user. So i modified the my code so that the file is uploaded to a temp location first and then moving it to the correct location. But even this is not working.
FileOutputStream outputStream = null;
FormFile formFile = null;
String tempFilePath = getServlet().getServletContext()
.getRealPath("/")
+ "uploads"
+ System.getProperty("file.separator") + "temp";
try
{
formFile = uploadForm.getFile();
boolean errorflag = false;
if(formFile.getFileSize() > 10660000)
{
request.setAttribute("error",
"File size cannot exceed 10MB!");
errorflag = true;
}
else
{
errorflag = validateFileUpload(request,
formFile, errorflag);
}
if(errorflag)
{
return gotoKnowledgeSharingPage(mapping,
request, actionHelper, session, userid,
instid);
}
File folder = new File(tempFilePath);
if(!folder.exists())
{
folder.mkdir();
}
outputStream = new FileOutputStream(new File(
tempFilePath, formFile.getFileName()));
outputStream.write(formFile.getFileData());
}
finally
{
if(outputStream != null)
{
outputStream.flush();
outputStream.close();
}
}
String finalFilePath = getServlet().getServletContext()
.getRealPath("/")
+ "uploads"
+ System.getProperty("file.separator")
+ session.getAttribute("userid");
//+ System.getProperty("file.separator")
// + formFile.getFileName();
File oldPath = new File(tempFilePath
+ System.getProperty("file.separator")
+ formFile.getFileName());
// Move file to new directory
File newPath = new File(finalFilePath);
if(!newPath.exists())
{
newPath.mkdir();
}
boolean success = oldPath.renameTo(new File(
finalFilePath, formFile.getFileName()));
if(success)
{
actionHelper.insertIntoUploadTable(userid,
knowledgeForm, formFile.getFileName());
}
else
{
if(oldPath.exists())
{
oldPath.delete();
}
}
I have written a Java web application that allows a user to download files from a server. These files are quite large and so are zipped together before download.
It works like this:
1. The user gets a list of files that match his/her criteria
2. If the user likes a file and wants to download he/she selects it by checking a checkbox
3. The user then clicks "download"
4. The files are then zipped and stored on a servera
5. The user this then presented with a page which contains a link to the downloadable zip filea
6. However on downloading the zip file the file that is downloaded is 0 bytes in sizea
I have checked the remote server and the zip file is being created properly, all that is left is to serve the file the user somehow, can you see where I might be going wrong, or suggest a better way to serve the zip file.
The code that creates the link is:
<%
String zipFileURL = (String) request.getAttribute("zipFileURL"); %>
<p>Zip File Link</p>
The code that creates the zipFileURL variable is:
public static String zipFiles(ArrayList<String> fileList, String contextRootPath) {
//time-stamping
Date date = new Date();
Timestamp timeStamp = new Timestamp(date.getTime());
Iterator fileListIterator = fileList.iterator();
String zipFileURL = "";
try {
String ZIP_LOC = contextRootPath + "WEB-INF" + SEP + "TempZipFiles" + SEP;
BufferedInputStream origin = null;
zipFileURL = ZIP_LOC
+ "FITS." + timeStamp.toString().replaceAll(":", ".").replaceAll(" ", ".") + ".zip";
FileOutputStream dest = new FileOutputStream(ZIP_LOC
+ "FITS." + timeStamp.toString().replaceAll(":", ".").replaceAll(" ", ".") + ".zip");
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
dest));
// out.setMethod(ZipOutputStream.DEFLATED);
byte data[] = new byte[BUFFER];
while(fileListIterator.hasNext()) {
String fileName = (String) fileListIterator.next();
System.out.println("Adding: " + fileName);
FileInputStream fi = new FileInputStream(fileName);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(fileName);
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return zipFileURL;
}
A URL cannot access any files (directly) under WEB-INF. I'd suggest using a servlet to return the file from whatever location it was saved to
Would also suggest saving the file outside the context of your webapp