How to prevent AmplifyJS from not fetching objects from Public folder always? - aws-amplify

I'm using AmplifyJS to get object from my S3 bucket. But what I have niticed is that Amplify JS gets me objects either from public folder or some other user's folder. But I have a file at root location of my S3 bucket. How do I get that file from Amplify JS?
For example, if you refer https://aws-amplify.github.io/docs/js/storage#get post, you will see it always appends /public folder after my bucket name. This is what I'm trying to avoid.
Amplify forces me to have folders within my S3 buckets. It would be PUBLIC, PROTECTED or USER's CUSTOM folder.

I got an answer to my question. You can set a customPrefix prefix property while using Amplify JS. here is an example.
const customPrefix = {
public: ''
};
Storage.get("TestJson.json", { download: true, customPrefix: customPrefix })
.then(result => console.log(JSON.parse(result.Body.toString())))
.catch(err => console.log(err));

Related

Edge browser Native File System removeEntry use

I'm working with the newest version of Edge (Canary release 86.0.615.0) and I can get the new Native File System API showOpenFilePicker to let me access files but I can't find a reference to the directoryHandle functions including the removeEntry function if the user elects to remove the file. Am I missing a special flag? I have an Origin-Tracker code and I also have the experimental flag set for the Native File System API.
If you have a directory handle, you can delete files or folders as in the example below:
// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });
You can obtain a directory handle from the picker:
const directoryHandle = await window.showDirectoryPicker();
To iterate over the entries of a directory, you can use the code snippet below:
for await (const entry of directoryHandle.values()) {
console.log(entry.kind, entry.name);
}

How to get local file path of image file downloaded from Firebase Storage in React Native

In my React Native app, i need to
Upload an image to Firebase Storage
Then Download it and edit it (crop/rotate)
Upload the edited image the Firebase Storage again
I was able to upload the image, get its URL using the getDownloadURL() method, and display it using Image component as it takes the url input right away.
Now I need the local file path in order to edit and reupload the edited image to Firebase Storage.
This question explains a getFile() method, but I cant find it firebase docs.
Another question give some direction but its in JAVA.
Some Blogs mention using libraries such as react-native-fs, react-native-fetch-blob etc, but it appears they are trying to save the file in storage/gallery. That is unnecessary for my requirement (i dont want to save images in gallery). I probably just need the path to the cached image where it gets downloaded.
Can someone please explain how to get local file path of downloaded image file in React Native lingo ?
EDIT:
Not using Expo. And I want it to work with Android and iOS both.
npm install rn-fetch-blob
Follow these steps:
a) follow the installation instructions.
a2) if you want to manually install the package without using rnpm, go to their wiki.
b) Finally, that's how I made it possible to download files within my app:
const { config, fs } = RNFetchBlob
let PictureDir = fs.dirs.PictureDir // this is the pictures directory. You can check the available directories in the wiki.
let options = {
fileCache: true,
addAndroidDownloads : {
useDownloadManager : true, // setting it to true will use the device's native download manager and will be shown in the notification bar.
notification : false,
path: PictureDir + "/me_"+Math.floor(date.getTime() + date.getSeconds() / 2), // this is the path where your downloaded file will live in
description : 'Downloading image.'
}
}
config(options).fetch('GET', "http://www.example.com/example.pdf").then((res) => {
// do some magic here
})
OR
const { uri: localUri } = await FileSystem.downloadAsync(remoteUri, FileSystem.documentDirectory + 'name.ext');
install react-native-fs
yarn add react-native-fs
and can get temporary path like this
var RNFS = require('react-native-fs');
const imageUrl = `http://www.example.com/abc.png`;
const imagePath = `${Platform.OS==="android"?"/storage/emulated/0/Download":RNFS.TemporaryDirectoryPath}/${((Math.random() * 1000) | 0)}.jpeg`;
RNFS.downloadFile({
fromUrl: imageUrl,
toFile: imagePath
}).promise
.then((result) => {
console.log(imagePath); //here you get temporary path
})
.catch((e) => {
console.log(e,"error");
})

Restore Firestore database to exact state found in previous export

I have the following https callable cloud function that imports all documents found in a backup.
const path = `${timestamp}`;
const projectId = await auth.getProjectId();
// we change the action for importDocuments
const url = `https://firestore.googleapis.com/v1/projects/${projectId}/databases/(default):importDocuments`;
const backup_route = `gs://${BUCKET_NAME}/${path}`;
return client.request({
url,
method: 'POST',
data: {
inputUriPrefix: backup_route,
}
}).then(async (res: any) => {
console.log(`Began backup restore from folder ${backup_route}`);
return Promise.resolve(res.data.name);
}).catch(async (e) => {
return Promise.reject(new functions.https.HttpsError('internal', e.message));
})
I use to this function to restore the database to the exact state it was when it was exported.
The problem is that the import operation, does not affect documents that are not found in the export. So new documents added after the export will remain in the database.
The following quote from the documentation explains this behaviour:
If a document in your database is not affected by an import, it will remain in your database after the import.
Is deleting the whole database before starting the import operation my only option? I can not find an operation that achieves the desired behaviour.
The provided export mechansim isn't meant for what what most people would call a "backup" that would be "restored" in the event of data loss. It's simply an export. It useful for making a copy of a database to be imported elsewhere, making it easy to duplicate a database across environments without having to write a lot of code.
If you want a fresh copy of the database from an import with no other documents, you will have to wipe out what's there before importing.

Nextjs export clear "out" folder

I'm working with nextjs and this example https://github.com/zeit/next.js/tree/master/examples/with-static-export
in next.config.js i have code:
module.exports = {
async exportPathMap(defaultPathMap, { dev, dir, outDir, distDir, buildId, incremental }) {
// we fetch our list of posts, this allow us to dynamically generate the exported pages
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts?_limit=3'
)
const postList = await response.json()
// tranform the list of posts into a map of pages with the pathname `/post/:id`
const pages = postList.reduce(
(pages, post) =>
Object.assign({}, pages, {
[`/post/${post.id}`]: { page: '/post/[id]' },
}),
{}
)
// combine the map of post pages with the home
return Object.assign({}, pages, {
'/': { page: '/' },
})
},
}
Its fetch 3 posts and generate files - [id].html - its great!
But now i need to fetch new post and build page only for this new post but commad next export remove all files from out and create only one post.
What i need to do to keep old post and add new one on next export?
Example:
First next export with request for 3 posts from api
generate 3 post in folder "out"
change api url and run next export for 1 new post
summary i have 3 old post pages and 1 new in my "out" directory
How to do that?
Next can't do this out of the box, but you can set it up to do so. First, you'll need a system (database) of which pages have already been built. Second, you'll need some method of communicating with that database (api) to ask which pages should be built (eg, send over a list of pages and the api responds telling you which ones have not yet bene built). Then, tell your exportPathMap which pages to build. And finally, move your built pages out of out and into a new final/public directory.
By default, Next will build/export anything in the pages directory plus anything you set in exportPathMap, and put all of those in the out directory. You can override what it builds by passing a custom exportPathMap, and how you handle what goes into the out directory is up to you, so you can move those files to a different actual public directory and merge them with the old files.

Download a file from a URL to a user accessible location

I am building an app using Nativescript/Angular 2
I want to be able to download a file from a URL and save it to the device in a location the average user would have no problems finding it. I believe downloads would be the best place for this on both iOS and Android. Please correct me if I am wrong.
The file can be any file type, not just an image. So mainly spreadsheet, word document, pdf, png, jpg, etc.
I have searched online and through the documentation. The documentation describes a method called getFile which gets a file and saves it to your device.
I have implemented this in my code as follows:
download (id) {
console.log('Download Started');
getFile("https://raw.githubusercontent.com/NativeScript/NativeScript/master/apps/tests/logo.png").then(function (r) {
console.log(r.path);
}, function (e) {
//// Argument (e) is Error!
});
}
The problem with this is that it saves it to a non-user accessible location such as:
/data/user/0/com.myapp.example/files/logo.png
Update:
I have also tried specifying the path directly with:
fs.knownFolders.documents();
However, this method gets the documents folder for the current application that is NOT accessible by the user or external applications
After some unsuccessful attempts, I finally found how to save file to user "Downloads" folder (something like sdcard/Download). You can use android.os.Environment method to get this folder.
Add this in your component:
import { getFile } from 'tns-core-modules/http';
import * as fileSystem from "tns-core-modules/file-system";
import { isAndroid } from "tns-core-modules/platform";
import { alert } from "tns-core-modules/ui/dialogs";
declare var android;
<...>
public download (url, fileName) {
if (isAndroid) {
const permissions = require("nativescript-permissions");
permissions.requestPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, "I need these permissions because I'm cool")
.then(() => {
let downloadedFilePath = fileSystem.path.join(android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), fileName);
getFile(url, downloadedFilePath).then(resultFile => {
alert({
title: 'Saved!',
okButtonText: 'OK',
message: `File saved here:\n${resultFile.path}`
});
}, error => {
alert({
title: 'Error',
okButtonText: 'OK',
message: `${error}`
});
});
});
}
}
What else you should know:
1) There is no any kind of download indicator, standard system download bar also not appears, and I don't know how to solve this.
2) For iOS you may try to use
const filePath = fileSystem.path.join(fileSystem.knownFolders.ios.downloads().path, fileName);
getFile(url, filePath).then((resultFile) => {}, (error) => {});
I think, it's the shame that NS docs don't talk straight, that you can't save files in user accessible location only with NS functions. I figured it out only when I read comments in file /node_modules/tns-core-modules/file-system/file-system.d.ts
Hope this helps you.
To get it working on iPhone, you can do the following (TypeScript):
import { knownFolders, path } from "tns-core-modules/file-system";
let destination = path.join(knownFolders.documents(), "file_name.txt");
// logic to save your file here ...
// the important thing is that you have to save your file in knownFolders.documents()
Then in Info.plist, you have to add the following permissions:
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
Now if you go to your iPhone's Files app > On My iPhone > Your App's Name, you should see the file there.
Basically, the Documents folder is a private folder inside your application's directory that only you can see. However, when you enable the two permissions above, it allows file sharing so that your user can access the folder and its contents.
The same documentation says that you can specify the file location like this:
download (id) {
console.log('Download Started');
var folder = fs.knownFolders.documents();
var file = fs.path.join(folder.path, "logo.png");
var url = "https://raw.githubusercontent.com/NativeScript/NativeScript/master/apps/tests/logo.png"
getFile(url, file).then(function (r) {
console.log(r.path);
}, function (e) {
//// Argument (e) is Error!
});
}
disclaimer: never tried it myself, just read the docs ...
You can specify a filesystem path directly, like this:
var folder = fs.Folder.fromPath('/sdcard/Download');
Note that /sdcard/Download will only work on Android; you can replace it with whatever (publicly accessible) folder you want to save your data to.
There doesn't yet seem to be a cross-platform way to choose a folder path, so you'll have to work out something manually. See this GitHub thread for more.
I realize that this is an older thread, but perhaps this can help someone:
If you use currentApp(), instead of documents(), you can access the folder you need. For example:
var directories = fs.knownFolders.currentApp();
var folder = directories.getFolder('./nameofaccessiblefolder');
I know this thread is 3 years ago but in case you have the same issue, I hope this solution will save time for you.
I solved the same issue by adding android:requestLegacyExternalStorage="true" inside the AndroidManifest.xml file
follow the thread here

Resources