Skip to content
Last updated

Tải tệp lên và tải tệp xuống Cloud Phone

Hướng dẫn này trình bày toàn bộ quy trình: tải tệp cục bộ lên, xuất tệp từ Cloud Phone, thăm dò tác vụ bất đồng bộ và khôi phục sau khi hết thời gian chờ.

Chọn bề mặt API

BướcOpen APILocal API
Base URLhttps://api.morelogin.comhttp://127.0.0.1:40000
Xác thựcAuthorization: Bearer <token>Local API token
Yêu cầu URL tải lênPOST /cloudphone/uploadUrlPOST /api/cloudphone/upload/file/signedUrl
Đăng ký đối tượng đã tảiPOST /cloudphone/uploadFilePOST /api/cloudphone/upload/file
Truy vấn kết quả tải lênPOST /cloudphone/uploadFileResultPOST /api/cloudphone/upload/file/result
Yêu cầu xuất tệpPOST /cloudphone/downloadPOST /api/cloudphone/download
Truy vấn kết quả xuấtPOST /cloudphone/download/resultPOST /api/cloudphone/download/result

Ví dụ dùng Open API. Với Local API, hãy đổi URL cơ sở và đường dẫn theo bảng. Giữ id, fileId và downId ở dạng chuỗi; JavaScript không được chuyển chúng qua Number.

Lối tắt multipart của Local API

Nếu tệp nằm trên cùng máy với ứng dụng MoreLogin, có thể gửi trực tiếp. Phản hồi thành công là đối tượng rỗng và không có ID tác vụ. Dùng quy trình URL ký sẵn nếu cần theo dõi và thử lại có thể quan sát.

curl --request POST "http://127.0.0.1:40000/api/cloudphone/uploadFile" \
  --form 'id=1661515884160372' \
  --form 'uploadDest=/Download' \
  --form 'file=@./report.csv'

Quy trình tải lên

Cloud PhoneStorageMoreLogin APIClientCloud PhoneStorageMoreLogin APIClientloop[status 0]1. uploadUrlpresignedUrl2. PUT bytes3. uploadFilefileId4. uploadFileResultdeliver file
Cloud PhoneStorageMoreLogin APIClientCloud PhoneStorageMoreLogin APIClientloop[status 0]1. uploadUrlpresignedUrl2. PUT bytes3. uploadFilefileId4. uploadFileResultdeliver file

1. Yêu cầu URL ký sẵn

curl --request POST "https://api.morelogin.com/cloudphone/uploadUrl" \
  --header "Authorization: Bearer $MORELOGIN_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "1661515884160372",
    "fileName": "report.csv"
  }'

2. Gửi dữ liệu tệp đến kho lưu trữ

curl --location --request PUT \
  --upload-file "./report.csv" \
  "$PRESIGNED_URL"

3. Đăng ký đối tượng để phân phối

FILE_URL="${PRESIGNED_URL%%\?*}"

curl --request POST "https://api.morelogin.com/cloudphone/uploadFile" \
  --header "Authorization: Bearer $MORELOGIN_TOKEN" \
  --header "Content-Type: application/json" \
  --data "$(jq -n \
    --arg id '1661515884160372' \
    --arg url "$FILE_URL" \
    --arg dest '/Download' \
    '{id: $id, url: $url, uploadDest: $dest, uploadType: 1}')"

4. Truy vấn kết quả tải lên

curl --request POST "https://api.morelogin.com/cloudphone/uploadFileResult" \
  --header "Authorization: Bearer $MORELOGIN_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "1661515884160372",
    "fileId": "1661515884160111"
  }'

Lưu data.presignedUrl. Gửi tệp trực tiếp đến URL này mà không kèm Bearer token. Chỉ tiếp tục sau trạng thái HTTP thành công, đăng ký URL đối tượng và lưu data.fileId.

data / data.statusÝ nghĩaXử lý
nullTác vụ chưa hiển thịChờ rồi truy vấn lại
0Đang tải lênChờ rồi truy vấn lại
1Thành côngDừng truy vấn
2Thất bạiDừng và báo requestId

Quy trình tải xuống

Tải xuống là xuất tệp từ Cloud Phone sang URL tạm thời. Lưu data.downId và truy vấn cho đến trạng thái kết thúc.

StorageCloud PhoneMoreLogin APIClientStorageCloud PhoneMoreLogin APIClientloop[status 10]1. download(id, filePath)export filedownId2. download/resultwrite filestatus 20, downUrl3. GET downUrl
StorageCloud PhoneMoreLogin APIClientStorageCloud PhoneMoreLogin APIClientloop[status 10]1. download(id, filePath)export filedownId2. download/resultwrite filestatus 20, downUrl3. GET downUrl

1. Yêu cầu xuất tệp

curl --request POST "https://api.morelogin.com/cloudphone/download" \
  --header "Authorization: Bearer $MORELOGIN_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "1661515884160372",
    "filePath": "/sdcard/Download/report.csv"
  }'

2. Chờ đến khi URL sẵn sàng

curl --request POST "https://api.morelogin.com/cloudphone/download/result" \
  --header "Authorization: Bearer $MORELOGIN_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "id": "1661515884160372",
    "downId": "1661515884160999"
  }'
data.statusÝ nghĩaXử lý
10Đang chạyChờ rồi truy vấn lại
20Thành côngTải từ data.downUrl
30Thất bạiDừng và báo requestId
40Đã hủyDừng; chỉ tạo tác vụ mới khi vẫn cần

3. Tải từ URL tạm thời

curl --location "$DOWN_URL" --output "./report.csv"

Ví dụ Python hoàn chỉnh

Ví dụ kiểm tra HTTP và code nghiệp vụ, tái sử dụng ID tác vụ và đặt hạn chót thăm dò.

import os
import time
from pathlib import Path

import requests

BASE_URL = "https://api.morelogin.com"
TOKEN = os.environ["MORELOGIN_TOKEN"]
PHONE_ID = "1661515884160372"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}


def api_post(path, payload):
    response = requests.post(
        f"{BASE_URL}{path}", json=payload, headers=HEADERS, timeout=30
    )
    response.raise_for_status()
    body = response.json()
    if body.get("code") != 0:
        raise RuntimeError(
            f"API error code={body.get('code')} msg={body.get('msg')} "
            f"requestId={body.get('requestId')}"
        )
    return body


def wait_for(path, payload, terminal, timeout=300):
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        body = api_post(path, payload)
        data = body.get("data")
        if data is not None and data.get("status") in terminal:
            return body
        time.sleep(2)
    raise TimeoutError(f"Timed out while polling {path}; keep the task ID")


def upload_to_phone(local_path, destination="/Download"):
    path = Path(local_path)
    signed = api_post(
        "/cloudphone/uploadUrl", {"id": PHONE_ID, "fileName": path.name}
    )
    presigned_url = signed["data"]["presignedUrl"]
    with path.open("rb") as stream:
        put_response = requests.put(presigned_url, data=stream, timeout=120)
    put_response.raise_for_status()

    object_url = presigned_url.split("?", 1)[0]
    created = api_post(
        "/cloudphone/uploadFile",
        {
            "id": PHONE_ID,
            "url": object_url,
            "uploadDest": destination,
            "uploadType": 1,
        },
    )
    file_id = created["data"]["fileId"]
    result = wait_for(
        "/cloudphone/uploadFileResult",
        {"id": PHONE_ID, "fileId": file_id},
        terminal={1, 2},
    )
    if result["data"]["status"] != 1:
        raise RuntimeError(f"Upload failed; requestId={result.get('requestId')}")
    return file_id


def download_from_phone(remote_path, local_path):
    created = api_post(
        "/cloudphone/download", {"id": PHONE_ID, "filePath": remote_path}
    )
    down_id = created["data"]["downId"]
    result = wait_for(
        "/cloudphone/download/result",
        {"id": PHONE_ID, "downId": down_id},
        terminal={20, 30, 40},
    )
    if result["data"]["status"] != 20:
        raise RuntimeError(f"Download export failed; requestId={result.get('requestId')}")

    with requests.get(result["data"]["downUrl"], stream=True, timeout=120) as response:
        response.raise_for_status()
        with open(local_path, "wb") as output:
            for chunk in response.iter_content(1024 * 1024):
                if chunk:
                    output.write(chunk)
    return down_id


upload_to_phone("./report.csv")
download_from_phone("/sdcard/Download/report.csv", "./downloaded-report.csv")

Danh sách kiểm tra production

  • Xác nhận code == 0; chỉ HTTP 200 không chứng minh nghiệp vụ thành công.
  • Giữ ID dạng chuỗi và truy vấn trạng thái trước khi lặp lại thao tác ghi sau timeout.
  • Không ghi token hoặc URL ký sẵn vào log; giữ requestId để hỗ trợ.
  • Giới hạn số truyền đồng thời và tuân thủ giới hạn yêu cầu.