flutter์์ image_picker ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
๐ image_picker ํ๋ฌ๊ทธ์ธ ํ์ด์ง
image_picker ํ๋ฌ๊ทธ์ธ์ 0.8.1์ด์์ ๋ฒ์ ์ ์ฌ์ฉํ๋ ค๋ฉด iOS 9.0์ด์, Android 4.3 ์ด์ํ์ํ๊ธฐ ๋๋ฌธ์ ์๋น์ค์์ ์ง์ํ๋ iOS, Android ๋ฒ์ ์ ํ์ธ ํ image_picker ํ๋ฌ๊ทธ์ธ์ ๋ฒ์ ์ ๋ง์ถฐ์ฃผ๋ฉด ๋๋ค.
* ๋๋ image_picker 0.8.4+11๋ฅผ ์ฌ์ฉํ๋ค.
iOS ์ฑ ์ค์
Add the following keys to your Info.plist file, located in <project root>/ios/Runner/Info.plist:
• NSPhotoLibraryUsageDescription - describe why your app needs permission for the photo library. This is called Privacy - Photo Library Usage Description in the visual editor.
-> ์ฌ์ฉ์ ์ฌ์ง ์จ๋ฒ์ ์ ๊ทผ ๊ถํ ์์ฒญ (ํ์)
• NSCameraUsageDescription - describe why your app needs access to the camera. This is called Privacy - Camera Usage Description in the visual editor.
-> ์ฌ์ฉ์ ์นด๋ฉ๋ผ์ ์ ๊ทผ ๊ถํ ์์ฒญ (์นด๋ฉ๋ผ๋ก ์ฌ์ง ์ดฌ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ๊ฒฝ์ฐ)
• NSMicrophoneUsageDescription - describe why your app needs access to the microphone, if you intend to record videos. This is called Privacy - Microphone Usage Description in the visual editor.
-> ์ฌ์ฉ์ ๋ง์ดํฌ ๊ถํ ์์ฒญ (๋น๋์ค ์ดฌ์ ๊ธฐ๋ฅ์ ์ฌ์ฉ ํ ๊ฒฝ์ฐ)
* Android๋ ๋ณ๋์ ์ถ๊ฐ ์ธํ ์ด ํ์ํ์ง ์๋ค๊ณ ๋์จ๋ค.
1. flutter์ image_picker ํ๋ฌ๊ทธ์ธ ์ถ๊ฐ.
flutter pub add image_picker
2. ์ด๋ฏธ์ง ์ ๋ก๋ ๊ธฐ๋ฅ์ด ํ์ํ ๊ณณ์ import.
import 'package:image_picker/image_picker.dart';
3. image_picker์ ์ฌ์ฉ ๊ธฐ๋ฅ์ ๋ฐ๋ผ ์์ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ๊ธฐ.
import 'package:image_picker/image_picker.dart';
...
final ImagePicker _picker = ImagePicker();
// Pick an image (์จ๋ฒ์์ ์ด๋ฏธ์ง ์ ํ)
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
// Capture a photo (์ฌ์ง ์ดฌ์)
final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
// Pick a video (์จ๋ฒ์์ ๋น๋์ค ์ ํ )
final XFile? image = await _picker.pickVideo(source: ImageSource.gallery);
// Capture a video (๋น๋์ค ์ดฌ์)
final XFile? video = await _picker.pickVideo(source: ImageSource.camera);
// Pick multiple images (๋ค์ค ์ด๋ฏธ์ง ์ ํ)
final List<XFile>? images = await _picker.pickMultiImage();
...โ
4. ๋๋ ์ฌ์ฉ์์ ํ๋กํ ์ด๋ฏธ์ง ๋ณ๊ฒฝ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ์ฌ์ง ์จ๋ฒ์์ ์ด๋ฏธ์ง 1์ฅ๋ง ์ ํํ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค.(์๋์ ์ฝ๋ ์ฐธ๊ณ )
// Stateful Widget
...
final ImagePicker _picker = ImagePicker();
XFile? _image;
Future getUserProfileFromLibrary() async {
final XFile? image = await _picker.pickImage(
source: ImageSource.gallery,
maxHeight: 600, // ์ต๋ ๋์ด ์ง์
maxWidth: 600, // ์ต๋ ๋๋น ์ง์
imageQuality: 50); // ์ด๋ฏธ์ง ํ๋ฆฌํฐ ์ง์
if (image != null) {
setState(() {
_image = image;
});
await postUserProfileToDB(image.path);
}
}
// ์ ํํ ์ด๋ฏธ์ง ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์์ ฏ ์ฝ๋
Image.file(File(_image?.path))
...
5. ์ ํํ ์ด๋ฏธ์ง๋ฅผ ์๋ฒ์ ๋ณด๋ด์ค ๋๋ dio ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์๋ค.
-> dio formData ๋ณด๋ด๊ธฐ ์ฐธ๊ณ
Future<void> postUserProfileToDB(photo) async {
final header = {
"Content-Type": "application/json",
};
var formData = FormData.fromMap({
'type': 'image',
'image': await MultipartFile.fromFile(photo,
contentType: MediaType('image', 'png')) //์ด ๋ถ๋ถ์ ์ค์ ํด์ฃผ์ง ์์๋๋ MIME ์๋ฌ๊ฐ ๋ฐ์ํ์๋ค.
});
final response = await dio.post(
'$baseUrl/images',
options: Options(headers: header),
data: formData,
).then((res) => print(res));
}
์์ฑํ๋ฉด! ๐