Im trying to zip my created folder. Right now im testing localy and it create folder but after that i want to zip it.
This is my code for zip:
public static void pack(final String sourceDirPath, final String zipFilePath) throws IOException {
Path p = Files.createFile(Paths.get(zipFilePath));
try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p))) {
Path pp = Paths.get(sourceDirPath);
Files.walk(pp).filter(path -> !Files.isDirectory(path)).forEach(path -> {
ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
try {
zs.putNextEntry(zipEntry);
Files.copy(path, zs);
zs.closeEntry();
} catch (IOException e) {
System.err.println(e);
}
});
} }
But im getting an error AccessDeniedException. Is there any option to zip created folder, i dont want to zip file because in that folder i will have subfolders, so i want to zip main folder. Any suggestion how can i achive that?
According to:
Getting "java.nio.file.AccessDeniedException" when trying to write to a folder
I think you should add the filename and the extension to your 'zipFilePath', for example: "C:\Users\XXXXX\Desktop\zippedFile.zip"
Related
How to download multiple files in a zip folder. I am using spring-boot and documents are saved in MongoDB using GridFS.
I was trying to download using FileSystemResource which takes File as an argument taking reference from https://simplesolution.dev/spring-boot-download-multiple-files-as-zip-file/
I tried to get download a resource from mongodb using below line of code and convert it into File object using
gridFsTemplate.getResource(GridFsFile).getFile();
I but it throws an error saying
GridFS resource can not be resolved to an absolute file path.
I have done using ByteArrayResource:
public void downloadZipFile(HttpServletResponse response, List<String> listOfDocIds) {
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=download.zip");
List<FileResponse> listOfFiles = myService.bulkDownload(listOfDocIds);// This call will fetch docs in the form of byte[] based on docIds.
try(ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) {
for(FileResponse fileName : listOfFiles) {
ByteArrayResource fileSystemResource = new ByteArrayResource(fileName.getFileAsBytes);
ZipEntry zipEntry = new ZipEntry(fileName.getFileName());
zipEntry.setSize(fileSystemResource.contentLength());
zipEntry.setTime(System.currentTimeMillis());
zipOutputStream.putNextEntry(zipEntry);
StreamUtils.copy(fileSystemResource.getInputStream(), zipOutputStream);
zipOutputStream.closeEntry();
}
zipOutputStream.finish();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
class FileResponse{
private String fileName;
private byte[] fileAsBytes;
// setter and getters
}
I am able to upload multiple files to s3 bucket at once. However there is a mismatch in the file name the one I provided and uploaded file. I am interested in file name as I need to generate cloud front signed url based on that.
File generation code
final String fileName = System.currentTimeMillis() + pictureData.getFileName();
final File file = new File(fileName); //fileName is -> 1594125913522_image1.png
writeByteArrayToFile(img, file);
AWS file upload code
public void uploadMultipleFiles(final List<File> files) {
final TransferManager transferManager = TransferManagerBuilder.standard().withS3Client(amazonS3).build();
try {
final MultipleFileUpload xfer = transferManager.uploadFileList(bucketName, null, new File("."), files);
xfer.waitForCompletion();
} catch (InterruptedException exception) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("InterruptedException occurred=>" + exception);
}
} catch (AmazonServiceException exception) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("AmazonServiceException occurred =>" + exception);
}
throw exception;
}
}
Uploaded file name is 94125913522_image1.png. As you can see first two characters disappeared. What am I missing here. I am not able to figure out. Kindly advice.
private static void writeByteArrayToFile(final byte[] byteArray, final File file) {
try (OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get(file.getName())))) {
outputStream.write(byteArray);
} catch (IOException exception) {
throw new FileIllegalStateException("Error while writing image to file", exception);
}
}
The reason of the problem
You lose the first two charecters of the file names because of the third argument of this method:
transferManager.uploadFileList(bucketName, null, new File("."), files);
What happens in this case
So, what is the third argument:
/**
...
* #param directory
* The common parent directory of files to upload. The keys
* of the files in the list of files are constructed relative to
* this directory and the virtualDirectoryKeyPrefix.
...
*/
public MultipleFileUpload uploadFileList(... , File directory, ...){...}
And how will it be used:
...
int startingPosition = directory.getAbsolutePath().length();
if (!(directory.getAbsolutePath().endsWith(File.separator)))
startingPosition++;
...
String key = f.getAbsolutePath().substring(startingPosition)...
Thus, the directory variable is used to define a starting index to trim file paths to get file keys.
When you pass new File(".") as a directory, the parent directory for your files will be {your_path}.
But this is a directory, and you need to work with files inside it. So the common part, retrieved from your directory file, is {your_path}./
That is 2 symbols more than you actually need. And for this reason this method trims the 2 extra characters - an extra shift of two characters when trimming the file path.
The solution
If you only need to work with the current directory, you can pass the current directory as follows:
MultipleFileUpload upload = transferManager.uploadFileList(bucketName, "",
System.getProperty("user.dir"), files);
But if you start working with external sources, it won't work. So you can use this code, which creates one MultipleFileUpload per group of files from one directory.
private final String PATH_SEPARATOR = File.separator;
private String bucketName;
private TransferManager transferManager;
public void uploadMultipleFiles(String prefix, List<File> filesToUpload){
Map<File, List<File>> multipleUploadArguments =
getMultipleUploadArguments(filesToUpload);
for (Map.Entry<File, List<File>> multipleUploadArgument:
multipleUploadArguments.entrySet()){
try{
MultipleFileUpload upload = transferManager.uploadFileList(
bucketName, prefix,
multipleUploadArgument.getKey(),
multipleUploadArgument.getValue()
);
upload.waitForCompletion();
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
private Map<File, List<File>> getMultipleUploadArguments(List<File> filesToUpload){
return filesToUpload.stream()
.collect(Collectors.groupingBy(this::getDirectoryPathForFile));
}
private File getDirectoryPathForFile(File file){
String filePath = file.getAbsolutePath();
String directoryPath = filePath.substring(0, filePath.lastIndexOf(PATH_SEPARATOR));
return new File(directoryPath);
}
The folder is /src/img. I need to get all file names(png files) from img folder and all subfolders.I dont know the full path to the folder so i need only to focus the project resourse. I need them in array. Using Java8 and Eclipse Mars.
So far this works:
try {
Files.walk(Paths.get("/home/fixxxer/NetBeansProjects/Installer/src/img/")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
System.out.println(filePath);
}
});
} catch (IOException ex) {
Logger.getLogger(InstallFrame.class.getName()).log(Level.SEVERE, null, ex);
}
The problem is that the folder need to be called like this:
/img cause it is inside the project
Thanks in advance :)
You can use relative paths.
Here, I am assuming that Installer is your project name. Otherwise, you can edit the relative path according to your project setup.
Files.walk(Paths.get(".//src//img//")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
System.out.println(filePath);
}
});
If you place your file
test.png
under
/src/resources/org/example
you can access it from your class
org.example.InstallFrame
using
final URL resource = InstallFrame.class.getResource("test.png");
respectively
final InputStream resourceAsStream = InstallFrame.class.getResourceAsStream("test.png");
First find the base path and then use in your code
String basePath = ClassLoader.getSystemResource("").getPath();
//move basepath to the path where img directory
//present in your project using ".."
//like basepath = basepath+"..\\..\\img"+
Files.walk(Paths.get(testPath)).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
System.out.println(filePath);
}
});
I have a cheerapp.mp3 in my /res/raw folder
so my code is
String filepath="/res/raw/cheerapp"; //or cheerapp.mp3
file = new File(filePath);
FileInputStream in = null;
try {
in = new FileInputStream( file );
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The error I got file not found. why?
Use assets folder and ...
InputStream sound = getAssets().open("filename.mp3");
... or raw folder and ...
InputStream sound = getResources().openRawResource(R.raw.filename);
if it doesn't help you, then check this
Never can you access resource files by path!
Because they are compiled in APK file installed in Android. You can only access resource within application by access its generated resource id, from any activity (context):
InputStream cheerSound = this.getResources().openRawResource(R.raw.cheerapp);
or from view:
InputStream cheerSound = this.getContext().getResources().openRawResource(R.raw.cheerapp);
In your case, you should store sound files in external sd-card, then can access them by path. For e.g, you store your file in sounds folder on your sd-card:
FileInputStream inFile = new FileInputStream("/mnt/sdcard/sounds/cheerapp.mp3");
NOTE: path starts with '/' is absolute path, because '/' represents root in Unix-like OS (Unix, Linux, Android, ...)
Maybe you could use the AssetManager to manage your resources. For example:
AssetManager manager = this.getContext().getAssets();
InputStream open;
try {
open = manager.open(fileName);
BitmapFactory.Options options = new BitmapFactory.Options();
...
} catch (IOException e) {
e.printStackTrace();
}
I am having an android application that is using an external jar that
has in addition to regular classes an html file.
Meaning my final apk root directory looks something like this
assests
res
AndroidManifest.xml
classes.dex
resources.arsc
helloworld.html
How can I access from my application to the last file
"helloworld.html"?
Android package hierarchy is not a like java application package.
So you can't access files like this.
I think you have to use this helloworld.html file in your application.
So put this file in /asset directory and in your activity code just get file using
getAssets().
also access file like: file:///android_asset/helloworld.html
Why not making a library project instead of a jar?
You have to replace the string "assets/SecureManifest.xml" with your file "helloworld.html"
public static InputStream getInputStreamFromApkResource(String apkFilePath, String apkResPath) throws IOException {
JarFile jarFile = new JarFile(apkFilePath);
JarEntry jarEntry = jarFile.getJarEntry(apkResPath);
return jarFile.getInputStream(jarEntry);
}
// Example usage reading the file "SecureManifest.xml" under "assets" folder:
File sdcard = Environment.getExternalStorageDirectory();
File apkFile = new File(sdcard, "file.apk");
if (apkFile.exists()) {
try {
InputStream is =getInputStreamFromApkResource(apkFile.toString(), "assets/SecureManifest.xml");
BufferedReader br = new BufferedReader( new InputStreamReader(is));
String str;
while ((str = br.readLine()) != null) {
Log.d("***", str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
The github gist can be found here