Uploading file to local Eclipse folder - java

I am trying to get the basics of I/O with Spring.
I am working through the File Upload samples. I want to store the files in a temporary folder in the project for testing.
I have this code:
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file){
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name)));
//get directory
stream.write(bytes);
stream.close();
I have created folder "files" within the project files. I want to know how to target the local folder.
I have tried using class File's alternate constructor.

The only way to write files in external(from web container) directory is to use the full direct path to the file. Just use the full file path in following File constructor.
File(String pathname)
Creates a new File instance by converting the given pathname string
into an abstract pathname.

Related

Google Drive API not downloading FIles (Java v3)

I'm using the code from here:
https://developers.google.com/drive/api/v3/manage-downloads#downloading_a_file
The code snippet I'm using is the following and placed in the main method:
String fileId = "some file ID";
OutputStream outputStream = new ByteArrayOutputStream();
driveService.files().get(fileId)
.executeMediaAndDownloadTo(outputStream);
I have found no sign of the code actually downloading the file, nor do I know where the file is IF it actually downloads.
I'm not sure if I am using the proper scope to gain permission to download files. I am able to upload, list, and delete files as long as I know the fileID, but downloading seems to not work.
private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE);
Alternatively, I'm trying to create a method to enact the download protocol like so:
private static void downloadFile(Drive service, File file (or String fileID)){
}
but am not sure on how to do so. I've tried looking for samples online but most are from v1 or v2 apis and don't seem to work for me.
Also, I've read somewhere that it is not possible to download a Folder. Instead, I have to download each item in the folder one by one.
So do I have to make an Arraylist/list/array of the fileIDs and iterate through it after initializing a variable to represent fileID?
Edit: Some progress has been made, but I still have some problems I'm trying to thrash out.
List<File> files = result.getFiles();
File newFile;
if (files == null || files.isEmpty()) {
System.out.println("No files found.");
} else {
System.out.println("Files:");
for (File file : files) {
System.out.printf("%s (%s)\n", file.getName(), file.getId());
String fileId = file.getId();
//System.out.println(fileId);
String fileName = file.getName();
//System.out.println(fileName);
OutputStream outputstream = new FileOutputStream();
service.files().get(fileId)
.executeMediaAndDownloadTo(outputstream);
outputstream.flush();
outputstream.close();
}
What I want:
The above code is in the main method. I don't know if this is the proper way to do it, but as the program fetches each file and executes the System.out.printf, I also want it to download that file (with the same mimeType, and pref the same name too) into the destination set in the OutputStream constructor (C://User//some name//Downloads).
What I've tried:
From what I've tested, it only downloads the first file exactly the way I want, but only because I specify the name and extension in OutputStream. I've initialized variables 'fileId' and 'fileName' so that they will change according to the info as the program fetches the metadata for the next file, but I don't know how to change or set multiple constructors into this code:
OutputStream outputstream = new FileOutputStream();
service.files().get(fileId)
.executeMediaAndDownloadTo(outputstream);
to download all the files.
My folder hierarchy in Google Drive is like this:
Logs
-- bin (folder)
---- bunch of .bin files
-- .xml file
-- .xml file
You are using a ByteArrayOutputStream object as the output of your download. If your program terminates without having saved the contents of this object somewhere, you will not be able to find this information in your computer's disk, as it is not written to it but rather saved in memory as a buffered byte-array (refer to the previous link for more information).
If you want to save the output of the download to the file, I suggest you use instead a FileOutputStream as the destination of your download. In order to do that, you have to modify your code as follows:
Add the appropriate import declaration:
import java.io.FileOutputStream;
Modify your outputStream variable assignment as follows:
OutputStream outputStream = new FileOutputStream('/tmp/downloadedfile');
Where the parameter passed to FileOutputStream should be the desired destination path of your download.
After writing any contents to your file, add the following lines of code:
outputStream.flush();
outputStream.close();
This will ensure that your file is being written to properly.
In regards to downloading a folder, you are completely right - you will first need to fetch the folder you want to download, and each of their children. In order to better understand how to do it, I suggest you check out the following answer: Download folder with Google Drive API
Edit - example downloading a folder
String destinationFolder = "/tmp/downloadedfiles/";
List<File> files = result.getFiles();
File newFile;
if (files == null || files.isEmpty()) {
System.out.println("No files found.");
} else {
System.out.println("Files:");
for (File file : files) {
System.out.printf("%s (%s)\n", file.getName(), file.getId());
String fileId = file.getId();
String fileName = file.getName();
OutputStream outputstream = new FileOutputStream(destinationFolder + fileName);
service.files().get(fileId)
.executeMediaAndDownloadTo(outputstream);
outputstream.flush();
outputstream.close();
}
}

Uploading to OpenStack Multipart With Path

I'm using java Jclouds to upload to a container inside an OpenStack Swift, the upload is going fine on the root, but when i pass a path(contains folders then the file), the file is uploaded but also creates another folder with the same name of the file. the original file name is 8mb.bin
the code is:
try {
ByteSource fileBytes = Files.asByteSource(file);
File file = new File(filePath);
String name = "test/test2/" + file.getName();
Blob blob = blobStore.blobBuilder(name)
.userMetadata(ImmutableMap.of("ContentType", contentType, "test", String.valueOf(test)))
.payload(fileBytes)
.contentLength(file.length())
.contentType(contentType)
.build();
///sednig the request
blobStore.putBlob(ContainerName, blob, multipart());
return contentLength;
}
and in the designated path its like this:
the folder 8mb.bin has the path inside it /slo/1522766773.076000/8200000/33554432 and then a file called 00000000 with the same size of the original file size.
how to solve this?
Thanks
jclouds implements Swift multipart using Static Large Objects. This has the limitation that parts exist in the same namespace as the manifest and modifying or deleting the parts invalidates the manifest. JCLOUDS-1285 suggests putting the parts in another container to clean up object listing although this requires some extra logic for deletes and overwrites.

File Upload in static/css/question_image folder

I want to upload a file in static/css/question_image which is a directory in my Spring Boot project.
By using below code i am able to upload the image but it is getting stored in my local system some directory and it doesn't appear in project folder structure.
Iterator<String> itr =multipartHttpServletRequest.getFileNames();
while(itr.hasNext()){
fileName = itr.next();
MultipartFile file =multipartHttpServletRequest.getFile(fileName);
System.out.println("File name is "+file.getOriginalFilename());
byte[] byteArr = file.getBytes();
File convFile = new File("static/"+file.getOriginalFilename());
convFile.createNewFile();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(convFile);
stream.write(byteArr);
stream.close();
I'm guessing your file is in the "static" sub-directory of the current directory, which, possibly, is the directory containing your JAR. You can't write back into the "project folder structure", as that appears to be in the JAR.
I suggest you rethink what you are intending to do with the output and where it needs to go.

How to create a file from classpath

I'm trying to create a new file in:
project/src/resources/image.jpg
as follows:
URL url = getClass().getResource("src/image.jpg");
File file = new File(url.getPath());
but I get error:
java.io.FileNotFoundException: file:\D:\project\dist\run560971012\project.jar!\image.jpg (The filename, directory name, or volume label syntax is incorrect)
What I'm I doing wrong?
UPDATE:
I'm trying to create a MultipartFile from it:
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "image/jpeg", IOUtils.toByteArray(input));
You are not passing the image data to the file!! You're trying to write an empty file in the path of the image!!
I would recommend our Apache friends FileUtils library (getting classpath as this answer):
import org.apache.commons.io.FileUtils
URL url = getClass().getResource("src/image.jpg");
final File f = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
FileUtils.copyURLToFile(url, f);
This method downloads the url, and save it to file f.
Your issue is that "image.jpg" is a resource of your project.
As such, it's embedded in the JAR file. you can see it in the exception message :
file:\D:\project\dist\run560971012\project.jar!\image.jpg
You cannot open a file within a JAR file as a regular file.
To read this file, you must use getResourceAsStream (as detailed in this this SO question).
Good luck

How to use classpath to specify a file location?

Here is the structure of my maven project:
main and test folders are under src folder, java and resources folders are under main folder,
in the resources folder, there is a csv file ready for reading.
src
--main
|-- java
|-- resources
|-- test.csv
test
As far as I know,
InputStream file = ClassLoader.getSystemResourceAsStream("test.csv");
could get the file content in the resources file.
However, in order to read and parse csv file based on supercsv library, I have to use the following code, but InputStream is not acceptable by CsvBeanReader method.
beanReader = new CsvBeanReader(new FileReader(CSV_FILENAME), CsvPreference.STANDARD_PREFERENCE);
So How can I not only getting the file from resource folder based on the maven structure, but also CsvBeanReader could accept the argument passed in.
Try using InputStreamReader instead of FileReader.
This is possible because the constructor of CsvBeanReader accepts the abstract class Reader:
CsvBeanReader(Reader reader, CsvPreference preferences)
//Constructs a new CsvBeanReader with the supplied Reader and CSV preferences.
You can construct the InputStreamReader using the InputStream you have obtained:
InputStreamReader(InputStream in)
InputStreamReader(InputStream in, Charset cs)
InputStreamReader(InputStream in, CharsetDecoder dec)
InputStreamReader(InputStream in, String charsetName)
You could wrap the java.io.InputStream with a java.io.InputStreamReader (which extends java.io.Reader) and pass it to the CsvBeanReader class.

Categories