Unable to store image url in Firestore - firebase

I successfully uploaded the image to firebase storage but I'm having trouble to store image url in firestore.
I received an error on console when trying to view the image:
core.js:6462 WARNING: sanitizing unsafe URL value
C:\fakepath\coke.jpg (see http://g.co/ng/security#xss)
GET unsafe:C:\fakepath\coke.jpg net::ERR_UNKNOWN_URL_SCHEME
Below is the html code: (details.page.html)
<!-- PRODUCT PICTURE INPUT -->
<ion-item>
<ion-label position="stacked">Product Picture</ion-label>
<ion-input accept="image/*" type="file" name="productPics" formControlName="productPics" (change)="showPreview($event)"></ion-input>
</ion-item>
Below is the typescript code: (details.page.ts)
ngOnInit() {
this.productForm = this.fb.group({
productPics: new FormControl('', Validators.compose([
Validators.required,
])),
});
this.resetForm();
}
showPreview(event: any) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
reader.onload = (e: any) => this.imgSrc = e.target.result;
reader.readAsDataURL(event.target.files[0]);
this.selectedImage = event.target.files[0];
} else {
this.imgSrc = "./assets/default_image.jpg";
this.selectedImage = null;
}
}
async saveProduct(formValue) {
this.isSubmitted = true;
this.product.userId = this.authService.getAuth().currentUser.uid;
if (this.productId) {
try {
this.product.createdAt = new Date().getTime();
console.log('product add');
console.log(this.productForm.value);
var filePath = `${formValue.productCategory}/${this.selectedImage.name}${new Date().getTime()}`;
const fileRef = this.storage.ref(filePath);
this.storage.upload(filePath, this.selectedImage).snapshotChanges().pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe((url) => {
formValue['productPics'] = url;
this.service.insertImageDetails(formValue);
this.resetForm();
})
})
).subscribe();
await this.productService.addProduct(this.product);
await this.loading.dismiss();
this.navCtrl.navigateBack('/vendor-tabs/home-vendor');
} catch (error) {
console.log('product dont add');
this.presentToast('Error trying to save');
}
}
}
Below is the service: (product.service.ts)
private productsCollection: AngularFirestoreCollection<Product>;
addProduct(product: Product) {
return this.productsCollection.add(product);
}
getProduct(id: string) {
return this.productsCollection.doc<Product>(id).valueChanges();
}
updateProduct(id: string, product: Product) {
return this.productsCollection.doc<Product>(id).update(product);
}
deleteProduct(id: string) {
return this.productsCollection.doc(id).delete();
}
insertImageDetails(image) {
this.productsCollection.add(image);
}

Related

Flutter make http api call when Firestore document changed

I'm trying to call data api when a firestore document is changed but I'm getting error: Error type 'null' is not a subtype of 'bool' with riverpod. What am I doing wrong? Thanks
final firebaseAuthProvider = Provider<FirebaseAuth>((ref) => FirebaseAuth.instance);
final authStateChangesProvider = StreamProvider<User?>((ref) => ref.watch(firebaseAuthProvider).authStateChanges());
final databaseProvider = Provider<DatabaseService?>((ref) {
final auth = ref.watch(authStateChangesProvider);
if (auth.asData?.value?.uid != null) {
return DatabaseService(uid: auth.asData!.value!.uid);
}
return null;
});
final firestoreDatabaseProvider = Provider<FirestoreDatabase?>((ref) {
final auth = ref.watch(authStateChangesProvider);
if (auth.asData?.value?.uid != null) {
return FirestoreDatabase(uid: auth.asData!.value!.uid);
}
return null;
});
final apiDataProvider2 = FutureProvider.autoDispose<ProfileUser?>((ref) {
final authUser = ref.watch(authStateChangesProvider);
final user = authUser.value;
if (user != null) {
final userValue = ref.watch(firestoreDatabaseProvider);
final dbProvider = ref.watch(databaseProvider);
var profileUser;
userValue?.getFirestoreUser().listen((event) {
profileUser = dbProvider!.getProfile();
});
if (profileUser) {
return profileUser;
} else {
return Future.value(null);
}
}
});
The problem is with profileUser; It is being returned before
var profileUser;
userValue?.getFirestoreUser().listen((event) {
profileUser = dbProvider!.getProfile();
});
if (profileUser) {
return profileUser;
} else {
return Future.value(null);
}
Try this instead:
var profileUser = (await userValue?.getFirestoreUser().first)!.getProfile();
if (profileUser) {
return profileUser;
} else {
return Future.value(null);
}

finding a nil value in session when accessing value in view

So i have a sessionStore:
class SessionStore: ObservableObject {
var handle: AuthStateDidChangeListenerHandle?
#Published var isLoggedIn = false
#Published var userInSession: User?
func listenAuthenticationState() {
handle = Auth.auth().addStateDidChangeListener({(auth, user) in
if let user = user {
let firestoreGetUser = Firestore.firestore().collection("users").document(user.uid)
firestoreGetUser.getDocument{(document, error) in
if let dict = document?.data() {
guard let decodedUser = try? User.init(fromDictionary: dict) else { return }
self.userInSession = decodedUser
print("decoded user = \(decodedUser)")
}
}
self.isLoggedIn = true
print("user logged in")
} else {
self.isLoggedIn = false
self.userInSession = nil
print("no one logged in")
}
})
}
func logout() {
do {
try Auth.auth().signOut()
} catch {
}
}
func unbind() {
if let handle = handle {
Auth.auth().removeStateDidChangeListener(handle)
}
}
deinit {
unbind()
}
}
Its working as expected, I am able to sign in etc.
I have the following to pull the current user data:
import Foundation
import Firebase
import FirebaseAuth
import FirebaseFirestore
class ProfileViewModel: ObservableObject {
var uid: String = ""
var email: String = ""
var username: String = ""
var profileURL: String = ""
var bio: String = ""
var occupation: String = ""
var city: String = ""
func LoadAUser(userId: String) {
Firestore.firestore().collection("users").document(userId).getDocument{(snapshot, error) in
guard let snap = snapshot else {
print("error fetching data")
return
}
let dict = snap.data()
guard let decodedUser = try? User.init(fromDictionary: dict!) else { return }
print("decoded user - load user - \(decodedUser)")
}
}
}
In my view im trying to call it like:
import SwiftUI
struct ProfileView: View {
#EnvironmentObject var session: SessionStore
#ObservedObject var profileViewModel = ProfileViewModel()
func loadUserData() {
profileViewModel.LoadAUser(userId: session.userInSession!.uid)
}
var body: some View {
VStack {
Text("Edit Profile")
.fontWeight(.semibold)
.font(.system(.title, design: .rounded))
.foregroundColor(Color("startColor"))
Spacer()
VStack(alignment: .leading) {
Text("view")
}.padding()
.onAppear(perform: loadUserData)
}
}
struct ProfileView_Previews: PreviewProvider {
static var previews: some View {
ProfileView()
}
}
Im using .onAppear(perform: loadUserData) which is causing an issue - Thread1: Fatal error: Unexpectedly found nil while unwrapping
I also tried:
init() {
profileViewModel.LoadAUser(userId: session.userInSession!.uid)
}
But this also causes the same error.
The thing is I should only be able to get to this view if I'm logged in as this already works:
struct InitialView: View {
#EnvironmentObject var session: SessionStore
func listen() {
session.listenAuthenticationState()
}
var body: some View {
Group {
if session.isLoggedIn {
MainView()
} else {
NavigationView {
SignUpView()
}
}
}.onAppear(perform: listen)
}
}
I have an initialView()
struct InitialView: View {
#EnvironmentObject var session: SessionStore
func listen() {
session.listenAuthenticationState()
}
var body: some View {
Group {
if session.isLoggedIn {
MainView()
} else {
NavigationView {
SignUpView()
}
}
}.onAppear(perform: listen)
}
}
which takes you to the MainView() which has tabs to control which screen you can navigate to, then from here i can go to ProfileView()
Anyway by the logic of provided code it is more correct to activate isLoggedIn in
let firestoreGetUser = Firestore.firestore().collection("users").document(user.uid)
firestoreGetUser.getDocument{(document, error) in
if let dict = document?.data() {
guard let decodedUser = try? User.init(fromDictionary: dict) else { return }
self.userInSession = decodedUser
print("decoded user = \(decodedUser)")
self.isLoggedIn = true // << here !!
print("user logged in")
}
}
So whats worked for me is passing in Auth instead of session data:
func loadUserData() {
profileViewModel.LoadAUser(userId: Auth.auth().currentUser!.uid)
}

upload image using file transfer ionic 3 not work on iOS

upload image using file transfer in ionic 3 works fine on android,
but give me error on iOS when try it in simulator ..
* this is the error:
My Ionic Code:
chooseImageFromGallery()
{
this.type="0"
const options: CameraOptions = {
quality: 60,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE,
saveToPhotoAlbum:true,
sourceType:0
}
this.camera.getPicture(options)
.then((imageData) => {
if (this.platform.is('ios'))
{
this.base64Image = imageData;
}
else
{
this.base64Image = imageData;
}
this.uploadimage(); // this function to upload img to server
},
(err) => {
}).then((path)=>{
})
}
uploadimage(){
this.photoSrc="";
this.translate.get("uploading Image...").subscribe(
value => {
this.sucesss=false
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: "file",
fileName:'test',
chunkedMode:false,
mimeType:"image/jpeg",
headers:{
Connection:"close"
},
httpMethod: "POST",
}
//------------ android ------------//
this.base64Image =this.base64Image
//------------ ios ------------//
//this.base64Image =this.base64Image.substring(28)
fileTransfer.upload(this.base64Image,encodeURI('mydomain/api/Product/upload'), options)
.then((data:any) => {
alert("upload success ")
}, (err) => {
this.translate.get( "error in upload Data").subscribe(
value => {
this.service.presentToast(value,2000)
}
)
})
})
}
using asp.net api2 .. My server Code :
[HttpPost]
[Route("upload")]
[AllowAnonymous]
public HttpResponseMessage uploadImage()
{
var request = HttpContext.Current.Request;
if (Request.Content.IsMimeMultipartContent())
{
foreach (string file in request.Files)
{
var postedFile = request.Files[file];
if (postedFile != null && postedFile.ContentLength > 0)
{
string root = HttpContext.Current.Server.MapPath("~/ServerImg");
root = root + "/" + postedFile.FileName;
postedFile.SaveAs(root);
//Save post to DB
return Request.CreateResponse(HttpStatusCode.Found, new
{
error = false,
status = "created",
path = root
});
}
else
{
return Request.CreateResponse(HttpStatusCode.NotFound, new
{
error = true
});
}
// var title = request.Params["title"];
}
// }
return null;
}
else
{
return Request.CreateResponse(HttpStatusCode.Forbidden, new
{
error = true
});
}
}
I spend more than 4 days.. but nothing is work for me ..
And this code works fine on Android but not iOS I don't know what's the wrong, I tried real iPhone and Xcode simulator and not worked
always upload error {"code":3... "http_status":500,..
Can anyone Help me please...

navigation after AsyncStorage.setItem: _this3.navigateTo is not a function

Currently, I am implementing a chat. After user pressed a chat button, the app will navigate the user to the Chat component. The chat content will simply store in firebase and chatId is needed to identify which chat belongs to the user.
Since I don't know how to pass props during navigation, I decided to save the CurrentChatId in AsyncStorage. After navigated to the Chat component, it will get the CurrentChatId from AsyncStorage so that I can map the chat content with the firebase.
However, I got the error _this3.navigateTo is not a function with code below:
let ref = FirebaseClient.database().ref('/Chat');
ref.orderByChild("chatId").equalTo(chatId).once("value", function(snapshot) {
chatId = taskId + "_" + user1Id + "_" + user2Id;
if (snapshot.val() == null) {
ref.push({
chatId: chatId,
taskId: taskId,
user1Id: user1Id,
user2Id: user2Id,
})
}
try {
AsyncStorage.setItem("CurrentChatId", chatId).then(res => {
this.navigateTo('chat');
});
} catch (error) {
console.log('AsyncStorage error: ' + error.message);
}
}
The function navigateTo is copied from the demo app of NativeBase
import { actions } from 'react-native-navigation-redux-helpers';
import { closeDrawer } from './drawer';
const {
replaceAt,
popRoute,
pushRoute,
} = actions;
export default function navigateTo(route, homeRoute) {
return (dispatch, getState) => {
const navigation = getState().cardNavigation;
const currentRouteKey = navigation.routes[navigation.routes.length - 1].key;
dispatch(closeDrawer());
if (currentRouteKey !== homeRoute && route !== homeRoute) {
dispatch(replaceAt(currentRouteKey, { key: route, index: 1 }, navigation.key));
} else if (currentRouteKey !== homeRoute && route === homeRoute) {
dispatch(popRoute(navigation.key));
} else if (currentRouteKey === homeRoute && route !== homeRoute) {
dispatch(pushRoute({ key: route, index: 1 }, navigation.key));
}
};
}
You should bind this to the function that contains the try & catch. The best practice is to add this bind the constructor of the the component:
constructor(props) {
super(props);
this.myFunctoin = this.myfuction.bind(this);
}
Finally, I solved the problem. It is really because this.navigateTo('chat'); is inside function(snapshot)
ref.orderByChild("chatId").equalTo(chatId).once("value", function(snapshot) {
chatId = taskId + "_" + user1Id + "_" + user2Id;
if (snapshot.val() == null) {
ref.push({
chatId: chatId,
taskId: taskId,
user1Id: user1Id,
user2Id: user2Id,
})
}
}
try {
AsyncStorage.setItem("CurrentChatId", chatId).then(res => {
this.navigateTo('chat');
});
} catch (error) {
console.log('AsyncStorage error: ' + error.message);
}
Take it out from the function will solve the problem.

How to access image src nativescript

How can I get photo src, from nativescript camera module?
public takePicture() {
cameraModule.takePicture().then(function(picture) {
console.log("Result is an image source instance");
var image = new imageModule.Image();
image.imageSource = picture;
console.dir(picture);
});
}
console.dir output:
=== dump(): dumping members ===
{
"android": {
"constructor": "constructor()function () { [native code] }"
}
}
=== dump(): dumping function and properties names ===
loadFromResource()
fromResource()
loadFromFile()
fromFile()
loadFromData()
fromData()
loadFromBase64()
fromBase64()
setNativeSource()
saveToFile()
height: 480
width: 640
=== dump(): finished ===
How do I get the image src ?
I want to upload it to firebase, so i need the src.
To upload to firebase, you need to upload the image via its path:
let imgsrc = this.imageSource.fromNativeSource(data);
let path = this.utils.documentsPath(randomName);
imgsrc.saveToFile(path, this.enums.ImageFormat.png);
this.firebase.uploadFile(path).then((uploadedFile: any) => {
this.appSettings.setString("fileName", uploadedFile.name);
this.router.navigate(['/soundcloud']);
this.LoadingIndicator.hide();
}, (error: any) => {
alert("File upload error: " + error);
});
}, (err: any) => {
alert(err);
});
Figured it out, this works:
public takePicture() {
cameraModule.takePicture().then((picture) => {
var image = new imageModule.Image();
image.imageSource = picture;
let savePath = fs.knownFolders.documents().path;
let fileName = 'img_' + new Date().getTime() + '_' + this.currentUserId.getValue() + '.' + enumsModule.ImageFormat.jpeg;
let filePath = fs.path.join( savePath, fileName );
picture.saveToFile(filePath, enumsModule.ImageFormat.jpeg);
this.photoService.uploadImage(filePath, fileName).then((data) => {
this._router.navigate(["/upload", fileName, this.currentUserId.getValue()]);
});
});
}

Resources