Uploading objects to google cloud storage bucket java - java

I want to upload simple image file to google cloud storage
when the upload is to root bucket upload happens smoothly but when i try to upload image to folder within a bucket it fails
following is my code to do so
static Storage sStorage;
public static void uploadFileToServer(Context context, String filePath) {
Storage storage = getStorage(context);
StorageObject object = new StorageObject();
object.setBucket(BUCKET_NAME);
File sdCard = Environment.getExternalStorageDirectory();
File file = new File(sdCard + filePath);
try {
InputStream stream = new FileInputStream(file);
String contentType = URLConnection.guessContentTypeFromStream(stream);
InputStreamContent content = new InputStreamContent(contentType, stream);
Storage.Objects.Insert insert = storage.objects().insert(BUCKET_NAME, null, content);
insert.setName(file.getName());
insert.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
i tried putting bucket name like [PARENT_BUCKET]/[CHILD_FOLDER]
but it doesn't work

GCS has a flat namespace, with "folders" being just a client-supported abstraction (basically, treating "/" characters in object names as the folder delimiter).
So, to upload to a folder you should put just the bucket name in the bucket field of the request, and put the folder at the beginning of of the object field. For example, to upload to bucket 'my-bucket', folder 'my-folder' and file-within-folder 'file', you'd set bucket name to 'my-bucket' and object name to 'my-folder/file'.

Related

Writing to file in Documents folder in internal storage

I've been trying to save text to a file in the documents folder in internal storage to be accessed by file manager so i can read it, I've tried several methods including using a writer, but I can't seem to get it to work, I'm not trying to save to external storage, I don't have external storage, only internal, and that's where my documents folder is, so I'm assuming I don't have to bother with the permissions in manifest, I threw in the setReadable just in case but I still can't find it in the documents folder, this is where I'm currently at.
public void writeToFile(String string){
try {
File file = new File(Environment.DIRECTORY_DOCUMENTS, "myFile.txt");
file.setReadable(true);
FileOutputStream stream = new FileOutputStream(file);
stream.write(string.getBytes(string));
stream.flush();
stream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
File file = new File(Environment.DIRECTORY_DOCUMENTS, "myFile.txt");
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "myFile.txt");

Transferring files from AWS lambda tmp folder to sftp server

I have created a AWS lambda function that takes some files from an S3 bucket, zips them and transfers the zipped file to a sftp server. When I look in the server, I see that the tmp folder has been carries over with the files and a tmp folder gets created inside the zip file. When I open the zip file, there is a tmp folder and inside that folder are the files that I had zipped. I have scoured the internet and AWS trying to figure out how to change the directory in AWS Lambda when I am retrieving the files to be zipped, but have not had any luck. I don't want to have a tmp folder in my zip file. When I unzip the zip file, I just want to see the files that I had selected to be zipped without any folders. Does anyone know how to do this? I am programming in Java.
My code is below.
private DownloadFile(){
File localFile = new File(fileName);
//pull data and audit files from s3 bucket
s3Client.getObject(new GetObjectRequest("pie-dd-demo/daniel20", fileName), localFile);
zipOS = new ZipOutputStream(fos);
//send files to be zipped
writeToZipFile(fileName, zipOS);
}
public static void writeToZipFile(String path, ZipOutputStream zipStream)
throws FileNotFoundException, IOException {
File aFile = new File(path);
FileInputStream fis = new FileInputStream(aFile);
ZipEntry zipEntry = new ZipEntry(path);
try {
zipStream.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipStream.write(bytes, 0, length);
System.out.println(path + "write to zipfile complete");
}
} catch (FileNotFoundException exception) {
// Output expected FileNotFoundExceptions.
} catch (Exception exception) {
// Output unexpected Exceptions.
}
zipStream.closeEntry();
fis.close();
}
I think the problem is that you are creating a zip entry using new ZipEntry(path) and that means that the resulting zip file will contain the full path as the name of the zip entry.
You can retrieve the actual filename from a full path/file in Java as follows:
File f = new File("/tmp/folder/cat.png");
String fname = f.getName();
You can then use fname to create the zip entry by calling new ZipEntry(fname).

How to output updated image to gallery?

The exif interface is used in my application to write new data to a stored image,captured using the camera intent in Android.
The problem is when the image file is output to storage, my code for updating the attributes of the image doesn't actually update the stored image when I view details of the image in the gallery.
For example I use the UserComment tag to add some generic text as a test input but this is not displayed in the image's details on the device.
My question is, how can I check if the data is actually being written to the file?
If I know that the attributes are being appended to the image then I can debug the storage of the file as the problem.
This is the getOutputPhotoFile() method which retrieves the last captured image in the directory of the project:
private File getOutputPhotoFile() throws IOException {
File directory = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), getPackageName());
if (!directory.exists()) {
if (!directory.mkdirs()) {
Log.e(TAG, "Failed to create storage directory.");
return null;
}
}
String timeStamp = new SimpleDateFormat("yyyMMdd_HHmmss", Locale.ENGLISH).format(new Date());
File[] files = directory.listFiles();
File origFile = new File(directory.getPath(), "IMG_" + timeStamp + ".jpg");
if(files.length!=0) {
File newestFile = files[files.length-1];
origFile = new File(directory.getPath() + File.separator + newestFile.getName());
}
String mString = "Generic Text..";
ExifInterface exifFile = new ExifInterface(origFile.getAbsolutePath());
exifFile.setAttribute("UserComment", mString);
exifFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE,
String.valueOf(latituteField.toString()));
exifFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE,
String.valueOf(longitudeField.toString()));
exifFile.saveAttributes();
return origFile;
}
Upon looking into ExifInterface API, it seems that there is no Exif TAG with the name "UserComment".
It seems that it only supports TAGs mentioned in the given API.
After setting the location values, you can use same ExifInterface API getAttribute(ExifInterface.TAG_GPS_LATITUDE,) and getAttribute(ExifInterface.TAG_GPS_LONGITUDE) to check whether the file has the values set.

Is there a way to upload file to Google Drive from InputStream in Drive SDK?

I have to load some data to Google Drive, but I can't use recommended by Drive SDK way to do it:
FileContent fileContent = new FileContent(mimeType, dataFile);
try {
File file = service.files().insert(body, fileContent).execute();
return file;
} catch (IOException e) {
System.out.println("An error occured: " + e);
return null;
}
because my data isn't always has the java.io.File as a source. Sometimes it may be an InputStream from encrypted storage or from other cloud storage and therefore I can't get FileContent from it. Is there a way to load data from InputStream to Google Drive without their intermediate storing on file system (as for Dropbox API method "putFileOverwrite", for example)?
Check this out
File file= drive.files().insert(body,
new InputStreamContent(
fileItemStream
.getContentType(),
new ByteArrayInputStream(
IOUtils.toByteArray(fileInputStream)))).execute;

Amazon Web Services (AWS) S3 Java create a sub directory (object)

I am familiar with AWS Java SDK, I also tried to browse the corresponding Javadoc, but I could not realize how do I create a sub directory, i.e., a directory object within a bucket, and how do I upload files to it.
Assume bucketName and dirName correspond to already existing bucket (with public permission) and a new (object) directory which needs to be created within the bucket (i.e. bucketName/dirName/)
I have tried the following:
AmazonS3Client s3 = new AmazonS3Client(
new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
s3.createBucket(bucketName + "/" + dirName); //throws exception
which throws an exception on the second line.
A short snippet which creates a sub-directory and uploads files to it will be deeply appreciated.
There are no "sub-directories" in S3. There are buckets and there are keys within buckets.
You can emulate traditional directories by using prefix searches. For example, you can store the following keys in a bucket:
foo/bar1
foo/bar2
foo/bar3
blah/baz1
blah/baz2
and then do a prefix search for foo/ and you will get back:
foo/bar1
foo/bar2
foo/bar3
See AmazonS3.listObjects for more details.
Update: Assuming you already have an existing bucket, the key under that bucket would contain the /:
s3.putObject("someBucket", "foo/bar1", file1);
s3.putObject("someBucket", "foo/bar2", file2);
...
Then you can list all keys starting with foo/:
ObjectListing listing = s3.listObjects("someBucket", "foo/");
S3 doesn't see directories in the traditional way we do this on our operating systems.
Here is how you can create a directory:
public static void createFolder(String bucketName, String folderName, AmazonS3 client) {
// create meta-data for your folder and set content-length to 0
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(0);
// create empty content
InputStream emptyContent = new ByteArrayInputStream(new byte[0]);
// create a PutObjectRequest passing the folder name suffixed by /
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,
folderName + SUFFIX, emptyContent, metadata);
// send request to S3 to create folder
client.putObject(putObjectRequest);
}
As casablanca already said you can upload files to directories like this:
s3.putObject("someBucket", "foo/bar1", file1);
Read the whole tutorial here for details, and the most important thing is you will find info how to delete the directories.
In newer versions of the SDK, you can do something like this (no need to create empty InputStream) to create an empty folder:
String key = parentKey + newFolderName;
if (!StringUtils.endsWith(key, "/")) {
key += "/";
}
PutObjectRequest putRequest = PutObjectRequest.builder()
.bucket(parent.getBucket())
.key(key)
.acl("public-read")
.build();
s3Client.putObject(putRequest, RequestBody.empty());
Leaving this answer here just in case someone stumbles upon this. I have been using aws sdk version - 1.11.875 and the following successfully created a folder for me when trying to upload a file into S3 bucket. I did not have to explicitly create the folder as mentioned in the earlier answer.
private void uploadFileToS3Bucket(final String bucketName, final File file) {
final String fileName = "parent/child/" + file.getName();
final PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file);
amazonS3.putObject(putObjectRequest);
}
This will create the parent and parent/child folders in the specified S3 bucket and upload the file into child folder.
This worked for me. I used spring boot and file uploaded according to Multipart mechanism. I wanted to save my images inside the photos folder in my aws s3 bucket. My need is save like this photos/mypic.jpg
----controller class method----
#PostMapping("/uploadFile")
public String uploadFile(#RequestPart(value = "file") MultipartFile file) throws IOException {
return this.amazonClient.uploadFile(file);
}
----service class (Implementation of controller)----
public String uploadFile(MultipartFile multipartFile) throws IOException {
try {
File file = convertMultiPartToFile(multipartFile);
String fileName = "photoes/"+generateFileName(multipartFile); //here give any folder name you want
uploadFileTos3bucket(fileName, file);
} catch (AmazonServiceException ase) {
logger.info("Caught an AmazonServiceException from GET requests, rejected reasons:");
}
return fileName;
}
The point is concatenate the folder name you want as prefix of the fileName
additionally I will show you how to delete folder. The point is give the folder name as the keyName(key name is uploaded object name in the s3 bucket.). I will show code snippet also.
----controller class method----
#DeleteMapping("/deleteFile")
public String deleteFile(#RequestPart(value = "keyName") String keyName) {
return this.amazonClient.deleteFile(keyName);
}
----service class (Implementation of controller)----
public String deleteFile(String keyName){
try {
s3client.deleteObject(new DeleteObjectRequest(bucketName, keyName));
} catch (SdkClientException e) {
e.printStackTrace();
}
return "deleted file successfully!";
}
for delete photos folder that we created , call method like this. deleteFile("photos/")
important:- / is mandatory
if You want to create folder then you need to use put command using following keys to create folder1 in:
in root of bucket -> folder1/folder1_$folder$
in path folder2/folder3/ -> folder2/folder3/folder1/folder1_$folder$
It is always all_previous_folders/folderName/folderName_$folder$

Categories