Ошибка [Ошибка: Создание Blobs из «ArrayBuffer» и «ArrayBufferview» не поддерживается]Javascript

Форум по Javascript
Ответить
Anonymous
 Ошибка [Ошибка: Создание Blobs из «ArrayBuffer» и «ArrayBufferview» не поддерживается]

Сообщение Anonymous »

Я пытаюсь загрузить изображения с моего устройства Galery в мое приложение React Native Expo с помощью Firebase, но я получаю ошибку OnSubmitCreatEService [Ошибка: создание каплей из «ArrayBuffer» и «ArrayBufferview» не поддерживается]. Может ли кто -нибудь помочь мне решить это, пожалуйста? Как только я загружаю изображение и проверяю форму < /p>
import React, { useEffect, useState } from 'react';
import {
View,
Text,
TextInput,
StyleSheet,
TouchableOpacity,
ActivityIndicator,
Alert,
ScrollView,
Pressable,
Image,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import * as ImagePicker from 'expo-image-picker';
import * as ImageManipulator from 'expo-image-manipulator';
import * as FileSystem from 'expo-file-system';

import { auth as firebaseAuth, db as firestoreDatabase, storage as firebaseStorage } from '../FirebaseConfig';
import {
addDoc,
collection,
doc,
onSnapshot,
orderBy,
query,
serverTimestamp,
} from 'firebase/firestore';
import { onAuthStateChanged } from 'firebase/auth';
import { ref as createStorageRef, uploadString, getDownloadURL } from 'firebase/storage';

const PRIMARY_COLOR = '#2B1E12';
const MUTED_TEXT_COLOR = '#6b6b6b';

export default function AddNewService({ navigation }) {
const [userIdentifier, setUserIdentifier] = useState(null);
const [isAuthReady, setIsAuthReady] = useState(false);

useEffect(() => {
return onAuthStateChanged(firebaseAuth, (user) => {
setUserIdentifier(user?.uid ?? null);
setIsAuthReady(true);
});
}, []);

// Formulaire
const [serviceName, setServiceName] = useState('');
const [servicePrice, setServicePrice] = useState('');
const [serviceHours, setServiceHours] = useState('0');
const [serviceMinutes, setServiceMinutes] = useState('30');

// Catégories
const [categoriesList, setCategoriesList] = useState([]);
const [isCategoryDropdownOpen, setIsCategoryDropdownOpen] = useState(false);
const [selectedCategory, setSelectedCategory] = useState(null); // { id, name }

// Image locale + téléversement
const [localImageUri, setLocalImageUri] = useState(null);
const [isUploadingImage, setIsUploadingImage] = useState(false);

const [isSavingService, setIsSavingService] = useState(false);

const isFormValid =
serviceName.trim() &&
selectedCategory &&
servicePrice !== '' &&
serviceHours !== '' &&
serviceMinutes !== '';

// Charger la liste des catégories
useEffect(() => {
const categoriesQuery = query(collection(firestoreDatabase, 'categories'), orderBy('name', 'asc'));
const unsubscribe = onSnapshot(categoriesQuery, (snapshot) => {
setCategoriesList(snapshot.docs.map((d) => ({ id: d.id, ...d.data() })));
});
return unsubscribe;
}, []);

async function requestMediaLibraryPermission() {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') throw new Error('Permission refusée');
}

async function pickImageFromLibrary() {
try {
await requestMediaLibraryPermission();

const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
quality: 0.9,
});
if (result.canceled) return;

const pickedAsset = result.assets[0];

// Redimensionner / compresser et forcer JPEG
const manipulatedImage = await ImageManipulator.manipulateAsync(
pickedAsset.uri,
[{ resize: { width: 1200 } }],
{ compress: 0.8, format: ImageManipulator.SaveFormat.JPEG }
);

// S’assurer d’un schéma file://
let fileUri = manipulatedImage.uri;
if (!fileUri.startsWith('file://')) {
const target = FileSystem.cacheDirectory + `service-${Date.now()}.jpg`;
await FileSystem.copyAsync({ from: fileUri, to: target });
fileUri = target;
}

setLocalImageUri(fileUri);
} catch (error) {
console.log('pickImageFromLibrary error', error);
Alert.alert('Image', 'Impossible d’ouvrir la galerie.');
}
}

function removeSelectedImage() {
setLocalImageUri(null);
}

async function uploadImageAndGetUrl(fileUri, workerId) {
setIsUploadingImage(true);
try {
const path = `services/${workerId}/${Date.now()}-${Math.random().toString(36).slice(2, 7)}.jpg`;
const base64 = await FileSystem.readAsStringAsync(fileUri, { encoding: FileSystem.EncodingType.Base64 });
const ref = createStorageRef(firebaseStorage, path);
const dataUrl = `data:image/jpeg;base64,${base64}`;
await uploadString(ref, dataUrl, 'data_url');
const url = await getDownloadURL(ref);
return url;
} finally {
setIsUploadingImage(false);
}
}

async function onSubmitCreateService() {
if (!userIdentifier) {
Alert.alert('Non connecté', 'Connecte-toi pour créer un service.');
return;
}
if (!isFormValid) {
Alert.alert('Champs manquants', 'Merci de remplir tous les champs requis.');
return;
}

setIsSavingService(true);
try {
const now = serverTimestamp();
const categoryReference = doc(firestoreDatabase, 'categories', selectedCategory.id);

// Téléversement de l’image si présente
let imageUrl = null;
if (localImageUri) {
imageUrl = await uploadImageAndGetUrl(localImageUri, userIdentifier);
}

// Création DANS la sous-collection workers/{userIdentifier}/services
await addDoc(collection(firestoreDatabase, 'workers', userIdentifier, 'services'), {
name: serviceName.trim(),
price: Number(servicePrice),
hours: Number(serviceHours) || 0,
minutes: Number(serviceMinutes) || 0,
image: imageUrl,
category: categoryReference,
visible: true,
createdAt: now,
updatedAt: now,
});

navigation.goBack();
} catch (error) {
console.log('onSubmitCreateService error', error);
Alert.alert('Erreur', 'Impossible de créer le service.');
} finally {
setIsSavingService(false);
}
}

if (!isAuthReady) return null;
if (isAuthReady && !userIdentifier) {
return (

Connecte-toi.

);
}

return (

Nouveau service

{/* Image */}

Image

{localImageUri ? (





Changer l’image



Supprimer



) : (


Ajouter une image

)}

{isUploadingImage && Téléversement…}


{/* Nom */}

Nom *



{/* Catégorie */}

Catégorie *
setIsCategoryDropdownOpen((v) => !v)}>

{selectedCategory ? selectedCategory.name : 'Choisir une catégorie'}



{isCategoryDropdownOpen && (

{categoriesList.map((category) => (
{
setSelectedCategory({ id: category.id, name: category.name });
setIsCategoryDropdownOpen(false);
}}
>
{category.name}

))}

)}


{/* Prix et durée */}


Prix ($) *



Heures *



Minutes *




{!isFormValid && * Champs obligatoires}


{isSavingService ? (

) : (
Créer
)}


navigation.goBack()}>
Annuler




);
}

const styles = StyleSheet.create({
center: { flex: 1, alignItems: 'center', justifyContent: 'center' },
screen: { padding: 16, marginTop: 36 },
title: { fontSize: 24, fontWeight: '800', color: '#111111', marginBottom: 12 },

field: { marginBottom: 12 },
label: { fontSize: 13, color: MUTED_TEXT_COLOR, marginBottom: 6 },

input: {
borderWidth: 1,
borderColor: 'rgba(43,30,18,0.18)',
borderRadius: 12,
paddingHorizontal: 14,
height: 48,
backgroundColor: '#ffffff',
},

// Image
pickButton: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
borderWidth: 1,
borderColor: 'rgba(43,30,18,0.18)',
borderRadius: 12,
paddingHorizontal: 14,
height: 48,
backgroundColor: '#ffffff',
},
pickButtonText: { color: '#222222', fontWeight: '600' },
imageRow: { flexDirection: 'row', alignItems: 'center', gap: 12 },
preview: { width: 96, height: 96, borderRadius: 12, backgroundColor: '#eeeeee' },
lightButton: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
backgroundColor: '#eeeeee',
borderRadius: 12,
paddingVertical: 10,
paddingHorizontal: 12,
borderWidth: 1,
borderColor: '#e2e2e2',
},
lightButtonText: { color: '#222222', fontWeight: '700' },

// Sélecteur catégorie
select: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
borderWidth: 1,
borderColor: 'rgba(43,30,18,0.18)',
borderRadius: 12,
paddingHorizontal: 14,
height: 48,
backgroundColor: '#ffffff',
},
selectText: { color: '#222222' },
selectList: {
backgroundColor: '#ffffff',
borderRadius: 12,
marginTop: 6,
borderWidth: 1,
borderColor: '#e9e9e9',
},
selectItem: { paddingVertical: 12, paddingHorizontal: 12 },
selectItemText: { fontSize: 16, color: '#111111' },

row: { flexDirection: 'row', alignItems: 'flex-start' },

hint: { color: MUTED_TEXT_COLOR, marginBottom: 8 },

primaryButton: {
backgroundColor: PRIMARY_COLOR,
height: 52,
borderRadius: 14,
alignItems: 'center',
justifyContent: 'center',
marginTop: 6,
},
primaryButtonDisabled: { opacity: 0.6 },
primaryButtonText: { color: '#ffffff', fontSize: 16, fontWeight: '700' },

cancelButton: { alignSelf: 'center', marginTop: 10 },
cancelButtonText: { color: '#333333', fontWeight: '600' },
});

< /code>
При необходимости это мой пакет.json < /p>
{
"name": "beautify-worker",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@react-native-async-storage/async-storage": "2.1.2",
"@react-native-community/datetimepicker": "8.4.1",
"@react-navigation/bottom-tabs": "^7.4.6",
"@react-navigation/native": "^7.1.17",
"@react-navigation/native-stack": "^7.3.25",
"expo": "53.0.20",
"expo-auth-session": "~6.2.1",
"expo-file-system": "~18.1.11",
"expo-image-manipulator": "~13.1.7",
"expo-image-picker": "~16.1.4",
"expo-secure-store": "~14.2.3",
"expo-status-bar": "~2.2.3",
"expo-web-browser": "~14.2.0",
"firebase": "^12.1.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-native": "0.79.5",
"react-native-dotenv": "^3.4.11",
"react-native-gesture-handler": "~2.24.0",
"react-native-google-places-autocomplete": "^2.5.7",
"react-native-reanimated": "~3.17.4",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1",
"react-native-url-polyfill": "^2.0.0",
"react-native-web": "^0.20.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/react": "~19.0.10",
"typescript": "~5.8.3"
},
"private": true
}



Подробнее здесь: https://stackoverflow.com/questions/797 ... are-not-su
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»