मुख्य सामग्री पर जाएं

React Native समर्थन

Dropup, React Native में native adapter के साथ काम करता है।

इंस्टॉलेशन

npm install @samithahansaka/dropup

# छवि चयन के लिए
npx expo install expo-image-picker

# दस्तावेज़ चयन के लिए
npx expo install expo-document-picker

# छवि हेरफेर के लिए (वैकल्पिक)
npx expo install expo-image-manipulator

बुनियादी सेटअप

import { useDropup } from '@samithahansaka/dropup';
import { NativeAdapter } from '@samithahansaka/dropup/native';
import * as ImagePicker from 'expo-image-picker';
import { View, Text, Button, Image, FlatList } from 'react-native';

function NativeUploader() {
const { files, actions, state } = useDropup({
// native adapter का उपयोग करें
adapter: NativeAdapter,

upload: {
url: 'https://your-api.com/upload',
},
});

const pickImage = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsMultipleSelection: true,
quality: 0.8,
});

if (!result.canceled) {
// File-like ऑब्जेक्ट्स में कनवर्ट करें
const files = result.assets.map(asset => ({
uri: asset.uri,
name: asset.fileName || 'photo.jpg',
type: asset.mimeType || 'image/jpeg',
}));

actions.addFiles(files);
}
};

return (
<View style={styles.container}>
<Button title="छवियां चुनें" onPress={pickImage} />

<FlatList
data={files}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<View style={styles.fileItem}>
{item.preview && (
<Image source={{ uri: item.preview }} style={styles.preview} />
)}
<Text>{item.name}</Text>
<Text>{item.status}</Text>
{item.status === 'uploading' && (
<Text>{item.progress}%</Text>
)}
</View>
)}
/>

<Button
title="सभी अपलोड करें"
onPress={() => actions.upload()}
disabled={state.isUploading}
/>
</View>
);
}

const styles = {
container: {
flex: 1,
padding: 20,
},
fileItem: {
flexDirection: 'row',
alignItems: 'center',
padding: 10,
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
preview: {
width: 50,
height: 50,
marginRight: 10,
borderRadius: 4,
},
};

Image Picker एकीकरण

गैलरी से चुनें

import * as ImagePicker from 'expo-image-picker';

const pickFromGallery = async () => {
// अनुमति का अनुरोध करें
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert('अनुमति आवश्यक है');
return;
}

const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsMultipleSelection: true,
quality: 0.8,
selectionLimit: 10,
});

if (!result.canceled) {
const files = result.assets.map(asset => ({
uri: asset.uri,
name: asset.fileName || `photo_${Date.now()}.jpg`,
type: asset.mimeType || 'image/jpeg',
size: asset.fileSize,
}));

actions.addFiles(files);
}
};

फ़ोटो लें

const takePhoto = async () => {
const { status } = await ImagePicker.requestCameraPermissionsAsync();
if (status !== 'granted') {
alert('कैमरा अनुमति आवश्यक है');
return;
}

const result = await ImagePicker.launchCameraAsync({
quality: 0.8,
allowsEditing: true,
aspect: [4, 3],
});

if (!result.canceled) {
const asset = result.assets[0];
actions.addFiles([{
uri: asset.uri,
name: `photo_${Date.now()}.jpg`,
type: asset.mimeType || 'image/jpeg',
}]);
}
};

Document Picker

import * as DocumentPicker from 'expo-document-picker';

const pickDocument = async () => {
const result = await DocumentPicker.getDocumentAsync({
type: ['application/pdf', 'application/msword'],
multiple: true,
});

if (result.type === 'success') {
actions.addFiles([{
uri: result.uri,
name: result.name,
type: result.mimeType,
size: result.size,
}]);
}
};

छवि संपीड़न (Native)

import * as ImageManipulator from 'expo-image-manipulator';

async function compressNativeImage(uri: string): Promise<string> {
const result = await ImageManipulator.manipulateAsync(
uri,
[{ resize: { width: 1200 } }],
{ compress: 0.7, format: ImageManipulator.SaveFormat.JPEG }
);

return result.uri;
}

// Dropup के साथ उपयोग करें
const { actions } = useDropup({
onFilesAdded: async (newFiles) => {
for (const file of newFiles) {
if (file.type.startsWith('image/')) {
const compressedUri = await compressNativeImage(file.uri);
actions.updateFileMeta(file.id, { compressedUri });
}
}
},
});

पूर्ण Native उदाहरण

import React from 'react';
import {
View,
Text,
TouchableOpacity,
Image,
FlatList,
StyleSheet,
ActivityIndicator,
} from 'react-native';
import { useDropup } from '@samithahansaka/dropup';
import { NativeAdapter } from '@samithahansaka/dropup/native';
import * as ImagePicker from 'expo-image-picker';
import * as DocumentPicker from 'expo-document-picker';

export default function FileUploader() {
const { files, actions, state } = useDropup({
adapter: NativeAdapter,
maxFiles: 10,
upload: {
url: 'https://your-api.com/upload',
headers: {
'Authorization': 'Bearer token',
},
},
onUploadComplete: (file) => {
console.log('अपलोड किया गया:', file.uploadedUrl);
},
onUploadError: (file, error) => {
console.error('विफल:', error.message);
},
});

const pickImages = async () => {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') return;

const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsMultipleSelection: true,
});

if (!result.canceled) {
const files = result.assets.map(asset => ({
uri: asset.uri,
name: asset.fileName || 'image.jpg',
type: asset.mimeType || 'image/jpeg',
}));
actions.addFiles(files);
}
};

const pickDocuments = async () => {
const result = await DocumentPicker.getDocumentAsync({
multiple: true,
});

if (!result.canceled) {
const files = result.assets.map(asset => ({
uri: asset.uri,
name: asset.name,
type: asset.mimeType,
size: asset.size,
}));
actions.addFiles(files);
}
};

const takePhoto = async () => {
const { status } = await ImagePicker.requestCameraPermissionsAsync();
if (status !== 'granted') return;

const result = await ImagePicker.launchCameraAsync({
quality: 0.8,
});

if (!result.canceled) {
const asset = result.assets[0];
actions.addFiles([{
uri: asset.uri,
name: `photo_${Date.now()}.jpg`,
type: 'image/jpeg',
}]);
}
};

const renderFile = ({ item }) => (
<View style={styles.fileItem}>
{item.preview && (
<Image source={{ uri: item.preview }} style={styles.thumbnail} />
)}
<View style={styles.fileInfo}>
<Text style={styles.fileName} numberOfLines={1}>
{item.name}
</Text>
<Text style={styles.fileStatus}>
{item.status === 'uploading'
? `अपलोड हो रहा है ${item.progress}%`
: item.status}
</Text>
</View>
<TouchableOpacity
onPress={() => actions.remove(item.id)}
style={styles.removeBtn}
>
<Text style={styles.removeText}>×</Text>
</TouchableOpacity>
</View>
);

return (
<View style={styles.container}>
{/* एक्शन बटन */}
<View style={styles.buttonRow}>
<TouchableOpacity style={styles.button} onPress={pickImages}>
<Text style={styles.buttonText}>गैलरी</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={takePhoto}>
<Text style={styles.buttonText}>कैमरा</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={pickDocuments}>
<Text style={styles.buttonText}>फ़ाइलें</Text>
</TouchableOpacity>
</View>

{/* फ़ाइल सूची */}
<FlatList
data={files}
keyExtractor={item => item.id}
renderItem={renderFile}
style={styles.list}
ListEmptyComponent={
<Text style={styles.emptyText}>कोई फ़ाइल चयनित नहीं है</Text>
}
/>

{/* अपलोड बटन */}
<TouchableOpacity
style={[styles.uploadBtn, state.isUploading && styles.uploadBtnDisabled]}
onPress={() => actions.upload()}
disabled={state.isUploading || files.length === 0}
>
{state.isUploading ? (
<View style={styles.uploadingRow}>
<ActivityIndicator color="white" />
<Text style={styles.uploadBtnText}>
अपलोड हो रहा है {state.progress}%
</Text>
</View>
) : (
<Text style={styles.uploadBtnText}>
{files.length} फ़ाइल(ें) अपलोड करें
</Text>
)}
</TouchableOpacity>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: '#fff',
},
buttonRow: {
flexDirection: 'row',
gap: 12,
marginBottom: 16,
},
button: {
flex: 1,
backgroundColor: '#f0f0f0',
padding: 16,
borderRadius: 8,
alignItems: 'center',
},
buttonText: {
fontWeight: '600',
},
list: {
flex: 1,
},
fileItem: {
flexDirection: 'row',
alignItems: 'center',
padding: 12,
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
thumbnail: {
width: 50,
height: 50,
borderRadius: 4,
marginRight: 12,
},
fileInfo: {
flex: 1,
},
fileName: {
fontWeight: '500',
},
fileStatus: {
color: '#666',
fontSize: 12,
marginTop: 2,
},
removeBtn: {
padding: 8,
},
removeText: {
fontSize: 24,
color: '#999',
},
emptyText: {
textAlign: 'center',
color: '#999',
marginTop: 40,
},
uploadBtn: {
backgroundColor: '#2196f3',
padding: 16,
borderRadius: 8,
alignItems: 'center',
marginTop: 16,
},
uploadBtnDisabled: {
backgroundColor: '#ccc',
},
uploadBtnText: {
color: 'white',
fontWeight: '600',
fontSize: 16,
},
uploadingRow: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
},
});

प्लेटफ़ॉर्म अंतर

सुविधाWebReact Native
Drag & dropहांनहीं
File pickerNativeexpo-image-picker
Preview URLsObject URLsFile URIs
File accessFile objectURI-based

Expo बनाम Bare React Native

Expo (Managed)

उपरोक्त सभी उदाहरण Expo managed workflow के साथ काम करते हैं।

Bare React Native

bare React Native के लिए, native मॉड्यूल इंस्टॉल करें:

# expo packages के बजाय
npm install react-native-image-picker
npm install react-native-document-picker

# यदि आवश्यक हो तो लिंक करें (पुराने RN संस्करण)
npx react-native link

फिर उन पैकेजों से संबंधित APIs का उपयोग करें।