'upload image and display it with React and python
hello i want to upload image profile to my localhost(localhost/react/uploads/) folder from app and display it and, also saving the path into mysql.
so far, by using postman, i was able to save the path in mysql and send the the image to folder uploads inside the backend
my problem is that when i run the app (expo-cli) and i add the image to the profile it doesn't send the image, but when i use postman to test the api it works, and the path of the file will be saved in mysql. my other problem is that when i use the postman to test api it will save the path of the file but it will upload the image in the directory folder(uploads) of the app. i want a way to upload the image to the localhost server or host like loaclhost/react/uploads.
app.py
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
db = SQLAlchemy(app)
ma = Marshmallow(app)
class User2(db.Model):
id = db.Column(db.Integer, primary_key=True)
usernm = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
email = db.Column(db.String(255))
phone = db.Column(db.String(255))
createdAt = db.Column(db.DateTime, default=datetime.datetime.now)
updatedAt = db.Column(db.DateTime, default=datetime.datetime.now)
public_id = db.Column(db.String(50), unique=True)
pic_profile = db.Column(db.String(255))
pathname = db.Column(db.String(50))
def __repr__(self):
return f"<User2 {self.usernm}>"
def save(self):
db.session.add(self)
db.session.commit()
@app.route('/upload', methods=['POST'])
def upload():
try:
if 'file' not in request.files:
return sennd.badRequest([], 'File tidak tersedia')
file = request.files['file']
if file.filename == '':
return sennd.badRequest([], 'File tidak tersedia')
if file and uploadconfig.allowed_file(file.filename):
uid = uuid.uuid4()
filename = secure_filename(file.filename)
renamefile = str(uuid.uuid4()) + "_" + filename
file.save(os.path.join(app.config['UPLOAD_FOLDER'], renamefile))
uploads = User2(pic_profile=renamefile)
db.session.add(uploads)
db.session.commit()
return sennd.success(
{
'pic_profile': renamefile,
},
"Sukses mengupload file"
)
else:
return sennd.badRequest([], 'File tidak diizinkan')
except Exception as e:
print(e)
@auth_ns.route('/signup')
class SignUp(Resource):
@auth_ns.expect(signup_model)
def post(self):
data = request.get_json()
usernm = data.get('usernm')
db_user = User2.query.filter_by(usernm=usernm).first()
if db_user is not None:
return jsonify({"message": f"User with username {usernm} already exists"})
new_user = User2(
public_id=str(uuid.uuid4(
)),
usernm=data.get('usernm'),
email=data.get('email'),
password=generate_password_hash(data.get('password')),
phone=data.get('phone'),
)
new_user.save()
return make_response(jsonify({"message": "User created successfuly"}), 201)
sennd.py
from flask import jsonify, make_response
def success(values, message):
res = {
'data': values,
'message': message
}
return make_response(jsonify(res)), 200
def badRequest(values, message):
res = {
'data': values,
'message': message
}
return make_response(jsonify(res)), 400
uploadconfig
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'pdf'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
signup.js
import React, { useState, useContext } from "react";
import { View, ScrollView, Image, TouchableOpacity } from "react-native";
import Text from "@kaloraat/react-native-text";
import UserInput from "../components/auth/UserInput";
import SubmitButton from "../components/auth/SubmitButton";
import axios from "axios";
import CircleLogo from "../components/auth/CircleLogo";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { AuthContext } from "../context/auth";
import AsyncStorage from "@react-native-async-storage/async-storage";
import FontAwesome5 from "react-native-vector-icons/FontAwesome5";
import * as ImagePicker from "expo-image-picker";
const Signup = ({ navigation }) => {
const [uploadImage, setUploadImage] = useState("");
const [usernm, setName] = useState("noura");
const [email, setEmail] = useState("[email protected]");
const [password, setPassword] = useState("nooe");
const [phone, setphone] = useState("1231");
const [loading, setLoading] = useState(false);
const [state, setState] = useContext(AuthContext);
const [pic_profile, setImage] = useState({ url: "", public_id: "" });
// console.log("NAVIGATION -> ", navigation);
const handleSubmit = async () => {
setLoading(true);
if (usernm!="" && password!="" && email!="" && phone!="" ) {
await fetch("http://127.20.10.6:5000/auth/signup", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
},
body: JSON.stringify({usernm:usernm, password:password, email:email, phone:phone})
}) .then(response =>response.json())
.then(resData => {
if(resData.message == "User created successfuly") {
setLoading(false);
alert(resData.message);
navigation.navigate("Home");
setState(data);
// save response in async storage
AsyncStorage.setItem("@auth", JSON.stringify(data));
} else {
setLoading(false);
alert(resData.message);
}
})
} else{
alert("All fields are required");
setLoading(false);
}
setLoading(false);
}
const handleUpload = async (e) => {
let permissionResult =
await ImagePicker.requestMediaLibraryPermissionsAsync();
// console.log(permissionResult);
// return;
if (permissionResult.granted === false) {
alert("Camera access is required");
return;
}
// get image from image
let pickerResult = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3],
base64: true,
});
// console.log("PICKER RESULT => ", pickerResult);
if (pickerResult.cancelled === true) {
return;
}
// save to state for preview
let base64Image = `data:image/jpg;base64,${pickerResult.base64}`;
setUploadImage(base64Image);
// send to backend for uploading to cloudinary
setLoading(false);
e.preventDefault();
let path = await uploadFileHandler(uploadFile);
dispatch(createItem({
...data,
pic_profile: path, // idk if this is the correct property name on the data
}, headers));
}
const uploadFileHandler = async (file) => {
const formData = new FormData();
formData.append('image', file);
setLoading(true);
try {
const config = {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
};
const fileURL = await fetch('http://127.20.10.6:5000/upload', formData, config);
setLoading(false);
return fileURL.data; //this is the path of the uploaded file
} catch (error) {
console.error(error);
setLoading(false);
}
};
//TODO: Submit handler
return (
<KeyboardAwareScrollView
contentCotainerStyle={{
flex: 1,
justifyContent: "center",
}}
>
<View style={{ marginVertical: 100 }}>
<CircleLogo>
{pic_profile && pic_profile.url ? (
<Image
source={{ uri: pic_profile.url }}
style={{
width: 190,
height: 190,
borderRadius: 100,
marginVertical: 20,
}}
/>
) : uploadImage ? (
<Image
source={{ uri: uploadImage }}
style={{
width: 190,
height: 190,
borderRadius: 100,
marginVertical: 20,
}}
/>
) : (
<TouchableOpacity onPress={() => handleUpload()}>
<FontAwesome5 name="camera" size={25} color="orange" />
</TouchableOpacity>
)}
</CircleLogo>
{pic_profile && pic_profile.url ? (
<TouchableOpacity onPress={() => handleUpload()}>
<FontAwesome5
name="camera"
size={25}
color="orange"
style={{ maringTop: -5, marginBottom: 10, alignSelf: "center" }}
/>
</TouchableOpacity>
) : (
<></>
)}
<Text title center>
Sign Up
</Text>
<UserInput
name="NAME"
value={usernm}
setValue={setName}
autoCapitalize="words"
autoCorrect={false}
/>
<UserInput
name="EMAIL"
value={email}
setValue={setEmail}
autoCompleteType="email"
keyboardType="email-address"
/>
<UserInput
name="PASSWORD"
value={password}
setValue={setPassword}
secureTextEntry={true}
autoComplteType="password"
/>
<UserInput
name="PHONE"
value={phone}
setValue={setphone}
secureTextEntry={true}
autoComplteType="phone"
/>
<SubmitButton
title="Sign Up"
handleSubmit={handleSubmit}
loading={loading}
/>
<Text small center>
Already Joined?{" "}
<Text onPress={() => navigation.navigate("Signin")} color="#ff2222">
Sign In
</Text>
</Text>
</View>
</KeyboardAwareScrollView>
);
};
export default Signup;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
