[Streamlit] 파일 업로드

원준·2023년 5월 25일
0

Streamlit

목록 보기
10/13
post-custom-banner

1. sidebar 생성

  • 보기 편한 방법을 위해 사이드에 선택 박스를 생성해서 메뉴를 설정해 사용하기 쉽게 만들어 넣자.

    menu = ['이미지 업로드', 'csv 업로드', 'About']
    
    choice = st.sidebar.selectbox('메뉴', menu)
    # 사이드에 list의 선택박스를 생성한다.

2. 이미지 업로드

  • 우선 Streamlit에서 제공하는 파일 업로드 함수를 사용해서 파일을 올릴 수 있는 버튼을 만들어 준다.

  • 만들면서 이미지의 파일만 들어갈 수 있도록 옵션에서 작성하여 제한해주면 좋다.

    # 작성 방법
    img_file = st.file_uploader('이미지를 업로드 하세요.', type=['png', 'jpg', 'jpeg'])

  • 파일을 업로드 하기 이전에 파일별로 겹치지 않게 고유의 이름을 가지도록 '시간'값을 가져와 이름을 바꾸도록 한다.

    • 이름이 겹치거나 할 경우 누가 누구 것인지 알기 어렵기때문에 설정하는 것이 좋다.
    # import 
    from datetime import datetime
    
    # main()
    if img_file is not None: # 파일을 넣을 경우에만 실행 함
      current_time = datetime.now() # 현재 시간 가져옴.
        # 2023-05-25 17:54:48.360 형태로 가져온다.
      filename = current_time.isoformat().replace(":", "_")
        # isoformat() : String으로 포멧 (변환)하겠다.
        # replace() : 파일을 저장하는데 일부 특수문자를 사용하지 못하는데 ':'를 '_'로 변환해준다.
      img_file.name = filename
        # 이미지 파일의 이름을 변환한 이름으로 변경한다.
  • 업로드 설정까지 했다면, 실제로 하드디스크에 저장되도록 코드를 작성해야한다.

    • 여러번 중복되면서 많이 사용하다보니 함수를 만들어 재활용 가능하도록 작성된 코드다.
    # 필요한 모듈 import
    import os
    
    # 파일 업로드 함수
    def save_uploaded_file(directory, file):
    	if not os.path.exists(directory): # 해당 이름의 폴더가 존재하는지 여부 확인
      	of.makedirs(directory) # 폴더가 없다면 폴더를 생성한다.
          
      with open(os.path.join(directory, file.name) 'wb) as f: #해당 경로의 폴더에서 파일의 이름으로 생성하겠다.
      	f.write(file.getbuffer()) # 해당 내용은 Buffer로 작성하겠다.
          	# 기본적으로 이미즈는 buffer로 저장되고 출력할때도 buffer로 출력한다.
      return st.success('파일 업로드 성공')
      
      
      
    # main() 사용
    save_uploaded_file('image', img_file)
    	# image_folder라는 폴더에 img_file을 저장하라.
  • 실제로 저장되는 것을 확인 할 수 있다.

3. CSV 파일 업로드

  • 기본 틀은 이미지 업로드와 다른 것이 없다.
    • 단, 파일 업로드를 위해 Streamlit에서 지원하는 파일 업로드 버튼에 대해 제한사항을 바꿔줘야 한다.
    # 제한 사항 변경
    csv_file = st.file_uploader('CSV 파일 업로드', type=['csv'])
    • 확실한 차이점이 있는 것을 확인 할 수 있다.
  • 버튼 이후에는 이미지 업로드와 똑같이 파일의 이름을 시간을 변경해서 업로드 함수를 사용하면 된다.
    • 실제로 들어간 것을 확인 할 수 있다.

4. 전체 코드

import streamlit as st

import pandas as pd

from datetime import datetime

import os # 경로 탐색

# 파일 업로드 함수
# 디렉토리 이름, 파일을 주면 해당 디렉토리에 파일을 저장해주는 함수
def save_uploaded_file(directory, file):
    # 1. 저장할 디렉토리(폴더) 있는지 확인
    #   없다면 디렉토리를 먼저 만든다.
    if not os.path.exists(directory):
        os.makedirs(directory)
    
    # 2. 디렉토리가 있으니, 파일 저장
    with open(os.path.join(directory, file.name), 'wb') as f:
        f.write(file.getbuffer())
    return st.success('파일 업로드 성공!')



# 기본 형식
def main():
    st.title('앱 데시보드')

    menu = ['이미지 업로드', 'csv 업로드', 'About']

    choice = st.sidebar.selectbox('메뉴', menu)
    
    if choice == menu[0]:
        st.subheader('이미지 파일 업로드')
        img_file = st.file_uploader('이미지를 업로드 하세요.', type=['png', 'jpg', 'jpeg'])
        if img_file is not None: # 파일이 없는 경우는 실행 하지 않음
            print(type(img_file))
            print(img_file.name)
            print(img_file.size)
            print(img_file.type)

            # 유저가 올린 파일을,
            # 서버에서 처리하기 위해서(유니크하게) 
            # 파일명을 현재 시간 조합으로 만든다. 
            current_time = datetime.now()
            print(current_time)
            print(current_time.isoformat().replace(':', "_") + '.jpg') #문자열로 만들어 달라
            # 파일 명에 특정 특수문자가 들어가면 만들수 없다.
            filename = current_time.isoformat().replace(':', "_") + '.jpg'
            img_file.name = filename

            save_uploaded_file('image', img_file)

            st.image(f'image/{img_file.name}')


    elif choice == menu[1]:
        st.subheader('csv 파일 업로드 ')

        csv_file = st.file_uploader('CSV 파일 업로드', type=['csv'])

        print(csv_file)
        if csv_file is not None:
            current_time = datetime.now()
            filename = current_time.isoformat().replace(':', '_') + '.csv'

            csv_file.name = filename

            save_uploaded_file('csv', csv_file)

            # csv를 보여주기 위해 pandas 데이터 프레임으로 만들어야한다.
            df = pd.read_csv('csv/'+filename)
            st.dataframe(df)


    else :
        st.subheader('이 대시보드 설명')

if __name__ == '__main__':
    main()
profile
공부해보자
post-custom-banner

0개의 댓글