Synology Download API

Namkoong Hugh·2023년 4월 21일
0

나의 친절한 맥북은 Synology를 쓰면 sinology라고 자꾸 자동변환해준다
시놀로지에 올라가 있는 파일을 Python 코드상에서 바로 불러와서 쓰고싶다는 생각을 함.
나한테 필요한건... "시놀로지의 특정 경로에 있는 파일을 다운로드하는 API"인데... 쓸데없이

엥 그 뭐드라 스토리지 서비스들 보면 막 그거 그 파일 링크 주면 그걸로 바로 접근할수 있잖아
이거 시놀로지에서 어케 하지??

같은 사고의 흐름을 거친 탓에.. synology direct link...url... 어쩌구 저쩌구로만 서치를 해버리고... 없단 결론을 내림....

  1. 시놀로지에서 "파일 공유" 기능이 있긴 한데 있는데 일단 사용자가 공유 링크를 먼저 생성해야되고 <- 여기에서 아웃.
  2. 그 공유 링크를 들어가도 파일이 바로 다운로드되는게 아니라 다운로드 UI 화면을 먼저 띄워줌 <- 나는 바로 데이터를 받아오는 링크를 원함

그래서 삽질을 통해 스스로 Authentification까지 갖춘 (사실상) 파일서버까지 다 구현하고 혼자 뿌-듯 해 하던 찰나

이거 API문서처럼 정리할... 아 ?

하고 그제서야... synology download api로 검색을 했더니만 바로 시놀로지 API가 있는 공식 문서가 나왔다는 슬픈 이야기.
근데 문서가 조?금 복잡해서 이거 사용하는데도 약간의 시행착오를 겪음

어쨌든 바로 본론

import requests
import json

URL = "https://my_awesome_nas.com"
# 반드시.. HTTPS를 사용하자
username = "username"
passwd = "passwd"
auth_query = { 
    'api': 'SYNO.API.Auth',
    'method': 'login'
    'version' : 3,
    'account': username,
    'passwd' : passwd,
    'format' : 'sid',
    'session' : 'dsm_info'
}

with requests.get(URL + "/webapi/auth.cgi", params = auth_query) as a:
    auth_info = json.loads(a.content)
    sid = auth_info["data"]["sid"]

시놀로지에서 제공하는 모든 API는 다음 포맷으로 이루어지는데, 인증을 위해 _sid parameter가 필요하다.
먼저 Auth API를 통해 로그인하고 세션 아이디 sid를 얻어오도록 하자.

깔끔함을 위해 문서에서 설명하는 URI의 ? 뒤에 나타나는 쿼리 관련 부분은 파이썬 코드상에서 params 매개변수로 빼줬다.

다운로드 API 사용은 다음과 같이 할 수 있다.

path = "/shared/path/to/file"
# 폴더 Path를 입력할 경우 폴더가 압축된 상태로 다운로드된다.
download_query = { 
    'api': 'SYNO.FileStation.Download',
    'version' : 2,
    'method': 'download',
    'path' :path,
    'mode' : 'open',
    '_sid' : sid
}

with requests.get(URL + "/webapi/entry.cgi", params=query) as b:
    # 만일 이미지 데이터를 코드 내에서 바로 사용하고자 할 땐
    from PIL import Image
    import io
    image = Image.open(io.BytesIO(b.content)
    # "나는 OpenCV가 좋아요"
    import cv2
    import numpy as np
    nparr = np.frombuffer(b.content, np.uint8)
    image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

    
with requests.get(URL + "/webapi/entry.cgi", params=query, stream=True) as b:
    # 파일시스템에 바로 다운로드하고자 할 때
    with open("filename", "wb") as f:
        for chunk in b.iter_content(chunk_size = 1024*1024):
            f.write(chunk)

만약 한꺼번에 여러 파일을 다운로드하고자 하면

path = '["/shared/path/to/file1","/shared/path/to/file2"]'

와 같은 형식으로 파라미터를 넘겨줄 수 있다.

위에 링크한 공식 문서에서 더 다양한 API가 있으니 참고하도록 하자.

0개의 댓글