Media

SocFlow 미디어 서버를 통해 이미지, 비디오 등의 파일을 업로드하고 관리할 수 있습니다. 업로드된 미디어는 고유한 ID와 URL을 받으며, 게시물 작성 시 사용할 수 있습니다.

미디어는 안전한 클라우드 스토리지에 저장되며, CDN을 통해 빠르게 전송됩니다. 이미지는 자동으로 최적화되고 리사이징됩니다.


POST/v1/media

미디어 업로드

파일을 SocFlow 미디어 서버에 업로드합니다. 두 가지 방식을 지원합니다:

  1. 파일 직접 업로드 (multipart/form-data): 로컬 파일을 직접 업로드
  2. URL 업로드 (application/json): 외부 URL에서 파일을 다운로드하여 업로드

지원 파일 형식

  • 이미지: JPG, PNG, GIF, WebP, SVG, HEIC, HEIF
  • 비디오: MP4, MOV, WebM, AVI, MPEG
  • 오디오: MP3, WAV, OGG
  • 기타: PDF, TXT 등

방법 1: 파일 직접 업로드 (multipart/form-data)

로컬 파일을 직접 업로드하는 방식입니다. multipart/form-data 형식으로 전송합니다.

요청 필드

  • Name
    file
    Type
    File
    Description

    필수. 업로드할 파일. 이미지, 비디오, 오디오 등 다양한 형식 지원.

  • Name
    title
    Type
    string
    Description

    (선택) 파일 제목. 제공하지 않으면 파일명이 사용됩니다.

  • Name
    description
    Type
    string
    Description

    (선택) 파일 설명. 제공하지 않으면 제목과 동일하게 설정됩니다.

요청

POST
/v1/media
curl --location 'https://api.socflow.app/api/v1/media' \
--header 'X-Secret-Token: {YOUR_API_KEY}' \
--form 'file=@"/path/to/image.jpg"' \
--form 'title="My Image"' \
--form 'description="Sample image description"'

방법 2: URL 업로드 (application/json)

외부 URL에서 파일을 다운로드하여 업로드하는 방식입니다. application/json 형식으로 전송합니다.

요청 필드

  • Name
    url
    Type
    string
    Description

    필수. 업로드할 파일의 URL. 유효한 HTTP/HTTPS URL이어야 합니다.

  • Name
    title
    Type
    string
    Description

    (선택) 파일 제목. 제공하지 않으면 URL에서 파일명을 추출하거나 기본값이 사용됩니다.

  • Name
    description
    Type
    string
    Description

    (선택) 파일 설명. 제공하지 않으면 제목과 동일하게 설정됩니다.

요청

POST
/v1/media
curl --location 'https://api.socflow.app/api/v1/media' \
--header 'X-Secret-Token: {YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data '{
  "url": "https://example.com/image.jpg",
  "title": "My Image",
  "description": "Sample image description"
}'

공통 응답

응답

200
OK
{
  "success": true,
  "message": "미디어 파일이 성공적으로 업로드되었습니다",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "object_key": "550e8400-e29b-41d4-a716-446655440000.jpg",
    "content_type": "image/jpeg",
    "size_bytes": 245678,
    "title": "My Image",
    "alt_text": "Sample image description",
    "version": 1,
    "created_at": 1704067200000
  }
}

GET/v1/media/:id

미디어 다운로드

업로드된 미디어 파일을 다운로드합니다. 파일의 고유 ID를 사용하여 접근할 수 있습니다.

URL 파라미터

  • Name
    id
    Type
    string
    Description

    필수. 미디어 파일의 고유 ID (UUID 형식)

조건부 요청 지원

이 엔드포인트는 HTTP 조건부 요청을 지원합니다:

  • If-None-Match: ETag 기반 캐시 검증 (304 Not Modified)
  • If-Modified-Since: 수정 시간 기반 캐시 검증
  • Range: 부분 다운로드 지원 (206 Partial Content)

요청

GET
/v1/media/:id
curl --location 'https://api.socflow.app/api/v1/media/550e8400-e29b-41d4-a716-446655440000' \
--output downloaded-file.jpg

응답 헤더

HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 245678
ETag: "abc123def456"
Last-Modified: Mon, 01 Jan 2024 00:00:00 GMT
Content-Disposition: attachment; filename="550e8400-e29b-41d4-a716-446655440000"
Accept-Ranges: bytes

GET/v1/media/users

미디어 목록 조회

API 키( X-Secret-Token )로 인증된 현재 사용자(owner) 가 업로드한 미디어 목록을 조회합니다. 페이지네이션과 필터링을 지원합니다.

쿼리 파라미터

  • Name
    page
    Type
    number
    Description

    (선택) 페이지 번호. 기본값: 1 (1 이상)

  • Name
    limit
    Type
    number
    Description

    (선택) 페이지당 항목 수. 기본값: 20 (1~100)

  • Name
    type
    Type
    string
    Description

    (선택) 미디어 타입 필터. 가능한 값: image, video, audio

  • Name
    search
    Type
    string
    Description

    (선택) 제목(title) 검색어 (부분 일치)

정렬/포함 규칙

  • 최신 업로드 순( created_at DESC )으로 정렬됩니다.
  • 삭제된 미디어( status = 'deleted' )는 제외됩니다.

요청

GET
/v1/media/users
curl --location 'https://api.socflow.app/api/v1/media/users?page=1&limit=20' \
--header 'X-Secret-Token: {YOUR_API_KEY}'

응답

200
OK
{
  "success": true,
  "data": {
    "result": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "object_key": "550e8400-e29b-41d4-a716-446655440000.jpg",
        "content_type": "image/jpeg",
        "size_bytes": 245678,
        "width": 1920,
        "height": 1080,
        "duration_ms": null,
        "title": "My Image",
        "alt_text": "Sample image",
        "tags_json": null,
        "metadata_json": null,
        "version": 1,
        "created_at": 1704067200000,
        "updated_at": 1704067200000,
        "download_url": "https://media.socflow.app/550e8400-e29b-41d4-a716-446655440000.jpg"
      }
    ],
    "usage": {
      "usage_size": 5234567890
    },
    "result_info": {
      "count": 20,
      "page": 1,
      "limit": 20,
      "total_count": 150,
      "total_pages": 8
    },
    "filters": {
      "type": "image"
    }
  }
}

DELETE/v1/media/:id

미디어 삭제

업로드한 미디어 파일을 삭제합니다. 본인이 업로드한 파일만 삭제할 수 있습니다.

URL 파라미터

  • Name
    id
    Type
    string
    Description

    필수. 삭제할 미디어 파일의 고유 ID (UUID 형식)

요청

DELETE
/v1/media/:id
curl --location --request DELETE 'https://api.socflow.app/api/v1/media/550e8400-e29b-41d4-a716-446655440000' \
--header 'X-Secret-Token: {YOUR_API_KEY}'

응답

200
OK
{
  "success": true,
  "message": "Media asset deleted successfully"
}

응답 필드

Media Asset 객체

  • Name
    id
    Type
    string
    Description

    미디어 파일의 고유 ID (UUID 형식)

  • Name
    object_key
    Type
    string
    Description

    스토리지에 저장된 파일의 키 (예: 550e8400-e29b-41d4-a716-446655440000.jpg)

  • Name
    content_type
    Type
    string
    Description

    파일의 MIME 타입 (예: image/jpeg, video/mp4)

  • Name
    size_bytes
    Type
    number
    Description

    파일 크기 (바이트)

  • Name
    width
    Type
    number | null
    Description

    (이미지/비디오) 가로 픽셀 수

  • Name
    height
    Type
    number | null
    Description

    (이미지/비디오) 세로 픽셀 수

  • Name
    duration_ms
    Type
    number | null
    Description

    (비디오/오디오) 재생 시간 (밀리초)

  • Name
    title
    Type
    string
    Description

    파일 제목

  • Name
    alt_text
    Type
    string
    Description

    파일 설명 (대체 텍스트)

  • Name
    tags_json
    Type
    string | null
    Description

    태그 정보 (JSON 문자열)

  • Name
    metadata_json
    Type
    string | null
    Description

    추가 메타데이터 (JSON 문자열)

  • Name
    version
    Type
    number
    Description

    파일 버전

  • Name
    created_at
    Type
    number
    Description

    생성 시각 (Unix timestamp, milliseconds)

  • Name
    updated_at
    Type
    number
    Description

    수정 시각 (Unix timestamp, milliseconds)

  • Name
    download_url
    Type
    string
    Description

    파일 다운로드 URL (목록 조회 시에만 포함)

Usage 객체

  • Name
    usage_size
    Type
    number
    Description

    사용자가 사용 중인 총 스토리지 용량 (바이트)

Result Info 객체

  • Name
    count
    Type
    number
    Description

    현재 페이지의 항목 수

  • Name
    page
    Type
    number
    Description

    현재 페이지 번호

  • Name
    limit
    Type
    number
    Description

    페이지당 최대 항목 수

  • Name
    total_count
    Type
    number
    Description

    전체 항목 수

  • Name
    total_pages
    Type
    number
    Description

    전체 페이지 수


사용 예시

이미지 갤러리 구현

async function createImageGallery() {
  const userId = 'user_123'

  // 이미지만 가져오기
  const response = await fetch(
    `https://api.socflow.app/api/v1/media/users/${userId}?type=image&page=1&limit=50`,
    {
      headers: {
        'X-Secret-Token': process.env.SOCFLOW_API_KEY,
      },
    },
  )

  const result = await response.json()
  const images = result.data.result

  console.log(`총 ${result.data.result_info.total_count}개의 이미지`)

  images.forEach((image) => {
    console.log(`
      제목: ${image.title}
      크기: ${(image.size_bytes / 1024).toFixed(2)}KB
      해상도: ${image.width}x${image.height}
      URL: ${image.download_url}
    `)
  })
}

await createImageGallery()

파일 업로드 및 게시물 작성

방법 1: 로컬 파일 업로드

async function uploadAndPost(file) {
  // 1. 파일 업로드
  const formData = new FormData()
  formData.append('file', file)
  formData.append('title', '내 게시물 이미지')

  const uploadResponse = await fetch('https://api.socflow.app/api/v1/media', {
    method: 'POST',
    headers: {
      'X-Secret-Token': process.env.SOCFLOW_API_KEY,
    },
    body: formData,
  })

  const uploadResult = await uploadResponse.json()
  const mediaId = uploadResult.data.id

  console.log(`업로드 완료: ${mediaId}`)

  // 2. 게시물 작성 (미디어 ID 사용)
  const postResponse = await fetch('https://api.socflow.app/api/v1/posts/feed', {
    method: 'POST',
    headers: {
      'X-Secret-Token': process.env.SOCFLOW_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      account_id: 'acc_instagram_12345',
      title: '새로운 게시물',
      content: '새로운 게시물입니다!',
      media_ids: [mediaId],
    }),
  })

  const postResult = await postResponse.json()
  console.log(`게시물 작성 완료: ${postResult.data.id}`)
}

방법 2: URL에서 파일 업로드

async function uploadFromUrlAndPost(imageUrl) {
  // 1. URL에서 파일 업로드
  const uploadResponse = await fetch('https://api.socflow.app/api/v1/media', {
    method: 'POST',
    headers: {
      'X-Secret-Token': process.env.SOCFLOW_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      url: imageUrl,
      title: '외부 이미지',
      description: 'URL에서 다운로드한 이미지',
    }),
  })

  const uploadResult = await uploadResponse.json()
  const mediaId = uploadResult.data.id

  console.log(`업로드 완료: ${mediaId}`)

  // 2. 게시물 작성 (미디어 ID 사용)
  const postResponse = await fetch('https://api.socflow.app/api/v1/posts/feed', {
    method: 'POST',
    headers: {
      'X-Secret-Token': process.env.SOCFLOW_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      account_id: 'acc_instagram_12345',
      title: '새로운 게시물',
      content: '외부 이미지를 사용한 게시물입니다!',
      media_ids: [mediaId],
    }),
  })

  const postResult = await postResponse.json()
  console.log(`게시물 작성 완료: ${postResult.data.id}`)
}

// 사용 예시
await uploadFromUrlAndPost('https://example.com/beautiful-image.jpg')

스토리지 용량 모니터링

async function monitorStorage(userId) {
  const response = await fetch(
    `https://api.socflow.app/api/v1/media/users/${userId}?page=1&limit=1`,
    {
      headers: {
        'X-Secret-Token': process.env.SOCFLOW_API_KEY,
      },
    },
  )

  const result = await response.json()
  const usageBytes = result.data.usage.usage_size
  const usageMB = (usageBytes / 1024 / 1024).toFixed(2)
  const usageGB = (usageBytes / 1024 / 1024 / 1024).toFixed(2)

  console.log(`현재 사용량: ${usageMB}MB (${usageGB}GB)`)

  const limit = 10 * 1024 * 1024 * 1024 // 10GB
  const usagePercent = ((usageBytes / limit) * 100).toFixed(1)

  console.log(`사용률: ${usagePercent}%`)

  if (usageBytes > limit * 0.9) {
    console.warn('⚠️ 경고: 스토리지 용량이 90% 이상 사용되었습니다!')
  }
}

await monitorStorage('user_123')

Was this page helpful?