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());
}
Related
I am fetching S3 objects and then sending the object in email as an attachment. I am saving the contents in a temporary file. For images the code is working fine but in case of documents (pdf, docx, csv) files the attachments are sent without extension so they are not accessible.
try {
fullObject = s3Client.getObject(new GetObjectRequest(bucketName, key));
System.out.println("fullObject: " + fullObject);
ObjectMetadata metadata = fullObject.getObjectMetadata();
System.out.println(" meta data type: " + metadata.getContentType());
InputStream inputStream = fullObject.getObjectContent();
String extension = fullObject.getKey();
int index = extension.lastIndexOf('.');
if(index > 0) {
extension = extension.substring(index + 1);
System.out.println("File extension is " + extension);
}
File file = File.createTempFile(key, "."+ extension );
System.out.println("file: "+ file);
try (OutputStream outputStream = new FileOutputStream(file)) {
IOUtils.copy(inputStream, outputStream);
} catch (Exception e) {
System.out.println("error in copying data from one file to another");
}
dataSource = new FileDataSource(file);
System.out.println("added datasource in the list");
attachmentsList.add(dataSource);
}
Upon going through this code, I got to know that the issue was not in this code but when I was setting the name of the File. I was setting filename without any extension, for example I set Filename as "temporary" this caused the documents to be saved with tmp extension. All I had to do was add the extension of the object with its name ("temporary.docx"), this solved the issue and attachments were sent properly and were accessible.
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
Scenario: Uncompress a tar file using Apache commons.
Problem: The tar i am using is a build tar which gets deployed into a web server. This tar contains duplicate entries like below.
appender_class.xml
APPENDER_CLASS.xml
when extracting using the below code only appender_class.xml is extracted but i want both the files how can i do that ? Renaming in fly is fine but how can i accomplish that?
public static void untar(File[] files) throws Exception {
String path = files[0].toString();
File tarPath = new File(path);
TarEntry entry;
TarInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = new TarInputStream(new FileInputStream(tarPath));
while (null != (entry = inputStream.getNextEntry())) {
int bytesRead;
System.out.println("tarpath:" + tarPath.getName());
System.out.println("Entry:" + entry.getName());
String pathWithoutName = path.substring(0, path.indexOf(tarPath.getName()));
System.out.println("pathname:" + pathWithoutName);
if (entry.isDirectory()) {
File directory = new File(pathWithoutName + entry.getName());
directory.mkdir();
continue;
}
byte[] buffer = new byte[1024];
outputStream = new FileOutputStream(pathWithoutName + entry.getName());
while ((bytesRead = inputStream.read(buffer, 0, 1024)) > -1) {
outputStream.write(buffer, 0, bytesRead);
}
System.out.println("Extracted " + entry.getName());
}
}
Try opening your FileOutputstream like this instead:
File outputFile = new File(pathWithoutName + entry.getName());
for(int i = 2; outputFile.exists(); i++) {
outputFile = new File(pathWithoutName + entry.getName() + i);
}
outputStream = new FileOutputStream(outputFile);
It should generate a file called APPENDER_CLASS.xml2 if it encounters a previously created file called APPENDER_CLASS.xml. If a APPENDER_CLASS.xml2 exists it will create a APPENDER_CLASS.xml3, ad infinitum.
File.exists() takes case sensitivity into account (windows filenames are case insensitive, whereas unix, linux and mac are case sensitive). Thus with the above code on case insensitive filesystems the file would be renamed and on case sensitive filesystems the file would not be renamed.
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