반응형

2년전 flutter로 프로젝트를 개발할 때 당시 null safety가 도입된지 초기여서 예제가 거의 없어 어려움을 겪었다. 많이 늦었고 이제는 자료도 많아졌지만 혹여나 필요한 사람이 있을수도 있기에 참고용으로 글을 써본다.

 

1. 간단한 설명

2. flutter 코드

3. php 코드

 

 

 

1. 간단한 설명

일단 원리는 flutter에서 이미지를 불러오고 이를 byte로 변환한다. 이 변환된 byte string을 php에서 받고 다시 이미지 파일로 만드는 것이다.

 

 

 

 

2. flutter 코드

먼저 flutter에서 앨범에 접근하고 이미지를 불러오기 위해 image_picker 패키지를 추가해준다.

https://pub.dev/packages/image_picker

 

dev_dependencies:
  flutter_test:
    sdk: flutter
  image_picker: ^0.7.2
  # 본필자는 아주 오래전에 flutter 프로젝트를 진행하여 버전이 매우 구버전이다.
  # 2023.01.14 기준으로 안드로이드 13에서도 작동은 한다.

 

 

import 'package:http/http.dart' as http; //이미지를 서버로 전송(post)하기 위한 패키지
import 'package:image_picker/image_picker.dart'; //image_picker 코드
import 'dart:convert'; //base64로 encode해서 서버로 보내기 위해 선언



PickedFile? _image1;
// 클래스 멤버변수 flutter위에 이미지를 저장하는 멤버변수 꼭 선언되어야한다.

final picker = ImagePicker(); 
//image_picker 클래스 객체 앨범에 접근해서 이미지를 불러오기 위해서 꼭 선언 되어야한다.





Container(
    height: 130,
    width: 130,
    child: _image1 == null //_image1이 선택되지 않았다면
        ? OutlinedButton.icon(
            onPressed: () {
              getGalleryImage1(); //누르면 사진을 선택하는 getGalleryImage1() method 호출
            },
            icon: Icon(
              Icons.add_a_photo,
              size: 24.0,
              color: Colors.grey,
            ),
            label: Text(
              '사진 추가',
              style: TextStyle(color: Colors.grey),
            ),
            style: ButtonStyle(),
          ) //사진 추가하라는 icon과 글자가 뜬다

        : Image.file(File(_image1!.path)), //사진이 있다면 그 사진 파일을 불러와 창에 보여준다
),
SizedBox(
  height: 50,
),
Container(
    child: ElevatedButton(
  style: ElevatedButton.styleFrom(primary: Colors.teal[300], elevation: 0, minimumSize: Size(100, 50)),
  child: Text(
    "전송",
    style: TextStyle(fontSize: 20),
  ),
  onPressed: () async {
      await write();
  },
))


// 위의 코드가 flutter 디자인부분이다.

먼저 위의 코드를 입력해서 이미지 파일을 불러올 틀과, 전송 버튼 gui를 디자인한다.

 

 

 

 

 //앨범에서 이미지를 flutter로 불러오는 method 부분이다.
  getGalleryImage1() async {
      var image = await picker.getImage(source: ImageSource.gallery); //이미지를 앨범에서 불러오는 method

      if (image == null) {
        //선택된 image가 없다면 그냥 return
        return;
      } else {
        //이미지가 선택됬다면 setstate를 통해서 화면에 선택된 이미지가 보여지게 업데이트하고 _image1에 저장
        setState(() {
          _image1 = image;
        });
        return;
      }

 }







//불러온 이미지 byte를 base64로 encode하고 서버로 전송한다.
write() async {
    try {
      String base64Image1 = "";
      

      if (null != _image1) {
        //_image1가 null 이 아니라면
        final bytes = File(_image1!.path).readAsBytesSync(); //image 를 byte로 불러옴
        base64Image1 = base64Encode(bytes); //불러온 byte를 base64 압축하여 base64Image1 변수에 저장 만약 null이였다면 가장 위에 선언된것처럼 공백으로 처리됨
      }

      final response = await http.post(
        //서버로 전송함
        Uri.parse("php 주소"), //php 주소 입력
        body: ({
          "base64Image1": base64Image1,
        }),
      );
      
      
    } catch (e) {
      print("인터넷 오류 발생")
    }
  }

위의 코드는 flutter method이다.

 

 

image_picker 패키지로 사진을 불러와 사진 자료형인 PickedFile? _image1;에 저장한다. gui에는 불러온 image를 setstate로 보여준다. 그 다음 전송버튼을 누르면 사진 파일을 바이트로 저장하고 이를 base64로 encode해서 string 자료형에 담아서 php 서버로 보낸다.

 

 

3. php 코드

write.php

 

<?php

    $base64Image1 = $_POST['base64Image1'];
    //flutter에서 전송한 이미지 byte를 base64 encode한 string을 받는다.


  	$DateTime = date('Y_m_d_h_i_s_', time());
    //나중에 이미지를 파일로 서버에 저장할때 이미지 이름으로 쓰기 위해 만들었다.
                    
    
    //이곳은 이제 사진있나 체크하고 작성하는곳                  
	if($base64Image1 != ""){
    
    		//filelocation은 파일을 저장할 위치와 파일 이름을 입력한다.
            // 나의 경우 root/images 폴더에 현재 시간과 무작위 15글자를 붙여서 이미지 파일 이름으로 저장했다.
            $filelocation = 'images/'.$DateTime.generateRandomString().".jpg";
            
            
            //base64로 encode되어있는 이미지 byte를 decode해준다.
            $Imagedata = base64_decode($base64Image1);
            
            
            //imagebyte를 jpeg로 만들고 새로 저장하는 함수이다. 이때 파일에 gps좌표값이나 기타 정보들이 모두 사라진다.
            //imagejpeg(imagecreatefromstring(이미지 바이트 string), 파일 위치, 사진 훼손도(= 압축률))
            //압축률이 크면 클수록 이미지 용량은 적어지나 사진 퀄리티가 낮아짐.
            imagejpeg(imagecreatefromstring($Imagedata), $filelocation, 80);
            
            //나중에 $base64Image1location 변수를 mysql로 넘겨서 테이블에 사진 파일 위치만 저장하면 된다.
            $base64Image1location = "php서버 도메인".$filelocation;
        }




//이미지를 파일을 서버에 저장할때 이미지 이름으로 쓰기 위해 만들었다.
    function generateRandomString($length = 15) {  
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';  
        $charactersLength = strlen($characters);  
        $randomString = '';  
        for ($i = 0; $i < $length; $i++) {  
        $randomString .= $characters[rand(0, $charactersLength - 1)];  
        }  
        return $randomString;  
    }


?>

설명은 주석에 모두 있으니 넘어가겠다...

반응형

+ Recent posts