Carica un file con l'API REST
Inizializza un caricamento REST, invia i byte in una richiesta o con multipart riprendibile, verifica il file archiviato e gestisci limiti, conflitti e risposte perse.
Ultima revisione
Gli screenshot mostrano l’interfaccia in inglese.
Carica un file con l’API REST aprendo una sessione, inviando i byte e leggendo la risposta finale del file. Una risposta di inizializzazione riserva un trasferimento, ma non significa che un file archiviato sia pronto. Il caricamento dei file piccoli termina con una PUT; i caricamenti multipart richiedono una chiamata di completamento separata.
Credenziale e destinazione
Apri Profilo → Chiavi API, seleziona Crea una chiave API, scegli Solo caricamento, poi apri Restrizioni e scadenza → Protocolli, scegli Solo quelli che scelgo e spunta API REST. Conserva in un luogo sicuro il token mostrato una sola volta dopo Genera la chiave. Puoi limitare una chiave a uno spazio di lavoro; tramite REST non puoi limitare una chiave ordinaria a una cartella.
Ti servono workspace_id della destinazione e, per una sottocartella, folder_id. Una chiave solo caricamento può aprire e interrogare le sessioni di caricamento, ma non elencare i file o gli spazi di lavoro. Ottieni gli ID con una credenziale di lettura autorizzata e distinta o dalle richieste dell’app autenticata. Non ampliare temporaneamente una chiave di caricamento di produzione solo per scoprire la destinazione.
Per trovare gli ID con una chiave di lettura autorizzata, impostala in modo sicuro come DOSYA_READ_API_KEY e richiedi l’elenco degli spazi di lavoro:
curl --fail-with-body --silent --show-error \
'https://api.dosya.dev/api/workspaces' \
-H "Authorization: Bearer $DOSYA_READ_API_KEY"
Copia id dello spazio di lavoro previsto da workspaces. Poi richiedi GET /api/files?workspace_id=THAT_ID con la stessa autorizzazione di lettura per esaminarne l’elenco alla radice; copia l’ID della cartella di destinazione dalle cartelle restituite. Per esaminare una cartella annidata fornisci anche folder_id. Usa questi ID con la credenziale di caricamento; i nomi leggibili non sono ID API.
Il tuo ruolo nello spazio di lavoro deve consentire upload_files e l’accesso alla pagina di caricamento. La destinazione deve rientrare nei limiti del membro, essergli visibile e consentire nuovi contenuti. Un blocco di cartella o file, una regola sulle estensioni, la quota del proprietario, il limite di spazio del membro o l’impostazione di concorrenza dello spazio di lavoro possono fermare il trasferimento.

Passaggi: carica un piccolo file di prova con curl
Imposta DOSYA_API_KEY in modo sicuro e sostituisci il segnaposto dello spazio di lavoro con un ID reale autorizzato. L’esempio richiede curl e Python 3. Crea un file di 12 byte e lo carica alla radice dello spazio di lavoro:
set -e
printf 'Hello dosya\n' > dosya-api-test.txt
DOSYA_WORKSPACE_ID='REPLACE_WITH_WORKSPACE_ID'
python3 - "$DOSYA_WORKSPACE_ID" <<'PYTHON' > upload-request.json
import json, sys
print(json.dumps({"workspace_id": sys.argv[1],
"file_name": "dosya-api-test.txt", "file_size": 12,
"mime_type": "text/plain"}))
PYTHON
curl --fail-with-body --silent --show-error \
'https://api.dosya.dev/api/upload/init' \
-H "Authorization: Bearer $DOSYA_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary @upload-request.json -o upload-init.json
DOSYA_UPLOAD_PATH=$(python3 -c 'import json; print(json.load(open("upload-init.json"))["upload_url"])')
curl --fail-with-body --silent --show-error --request PUT \
"https://api.dosya.dev$DOSYA_UPLOAD_PATH" \
-H "Authorization: Bearer $DOSYA_API_KEY" \
-H 'Content-Type: text/plain' \
--data-binary @dosya-api-test.txt -o upload-result.json
python3 -m json.tool upload-result.json
Fermati se l’inizializzazione non riesce; non eseguire la PUT con un percorso non aggiornato rimasto da un tentativo precedente. Aggiungi "folder_id": "REPLACE_WITH_FOLDER_ID" al JSON di inizializzazione per una cartella nota. I nomi vengono ripuliti da separatori di percorso, sequenze di attraversamento delle directory e caratteri di controllo, poi verificati rispetto al limite di 255 caratteri. Indica in file_size il numero effettivo intero di byte, non MB o una stringa formattata.
L’inizializzazione restituisce 201 con session_id, upload_url, workspace_id, file_name, file_size, mime_type, extension, region e resumable. Per un file fino a 52.428.800 byte (50 MiB) inclusi, resumable è nullo salvo richiesta di force_multipart: true. La regione proviene dallo spazio di lavoro; una regione fornita dal client non sposta il file.
La risposta 201 della PUT contiene ok: true e file, inclusi id, name, size_bytes, version, region, content_hash, hash_verified e etag. Confronta size_bytes con il file locale e conserva l’ID. Una chiave solo caricamento può verificare il completamento dallo stato della sessione; usa l’elenco file dell’app autenticata o una chiave di lettura per esaminare indipendentemente il file risultante. Il solo caricamento non crea un link pubblico né invia email a un destinatario.
Trasferimento multipart e ripresa
Oltre 50 MiB usa i valori resumable restituiti. Le parti sono di 10.485.760 byte (10 MiB), tranne l’ultima, che può essere più corta. total_parts è la dimensione dichiarata divisa per la dimensione della parte e arrotondata per eccesso. Per un file di dimensione positiva puoi richiedere anche force_multipart: true; il multipart forzato a zero byte viene rifiutato.
Per un file locale più grande crea un nuovo corpo di inizializzazione dalla sua dimensione effettiva anziché mantenere i valori di prova da 12 byte. Questo comando Python sostituisce upload-request.json usando lo spazio di lavoro già scelto; modifica path e aggiungi un folder_id noto se necessario:
python3 - "$DOSYA_WORKSPACE_ID" <<'PYTHON' > upload-request.json
import json, sys
from pathlib import Path
path = Path("REPLACE_WITH_LOCAL_FILE_PATH")
print(json.dumps({"workspace_id": sys.argv[1], "file_name": path.name,
"file_size": path.stat().st_size,
"mime_type": "application/octet-stream"}))
PYTHON
Esegui il precedente POST /api/upload/init con quel corpo, salva la risposta in upload-init.json e usa lo stesso file locale invariato nel programma seguente, che permette di riprendere il caricamento. Conserva il JSON dell’inizializzazione riuscita affinché un’esecuzione interrotta possa riprendere la stessa sessione. Il programma Python 3 seguente invia in sequenza le parti mancanti e completa il caricamento. Salvalo come resume-upload.py, imposta in modo sicuro la variabile d’ambiente DOSYA_API_KEY ed esegui python3 resume-upload.py PATH_TO_UNCHANGED_FILE upload-init.json. Richiede un’inizializzazione con resumable non nullo:
import json, os, sys
from pathlib import Path
from urllib.request import Request, urlopen
base = "https://api.dosya.dev"
init = json.loads(Path(sys.argv[2]).read_text())
r = init["resumable"]
if r is None:
raise SystemExit("Use the single PUT flow for this session")
file = Path(sys.argv[1])
if file.stat().st_size != init["file_size"]:
raise SystemExit("Local size changed; open a new upload session")
headers = {"Authorization": "Bearer " + os.environ["DOSYA_API_KEY"]}
def call(path, method="GET", body=None):
req = Request(base + path, data=body, method=method,
headers={**headers, "Content-Type": "application/octet-stream"})
with urlopen(req) as response:
return json.load(response)
state = call(r["status_url"])
if state["status"] == "complete":
print("Already complete; file:", state["file_id"])
raise SystemExit(0)
if state["status"] == "failed":
raise SystemExit("Session failed; open a fresh session and resend the file")
done = set(state["uploaded_parts"])
with file.open("rb") as stream:
for number in range(1, r["total_parts"] + 1):
chunk = stream.read(r["part_size"])
if number not in done:
call(r["part_upload_url"] + "/" + str(number), "PUT", chunk)
result = call(r["complete_url"], "POST", b"")
print("Stored file:", result["file"]["id"], "bytes:", result["file"]["size_bytes"])
Mantieni invariato il file locale; dimensioni uguali non garantiscono contenuti uguali. I numeri delle parti iniziano da uno e non devono superare total_parts. Inviare di nuovo una parte già registrata restituisce l’ETag salvato con already_uploaded: true; non sostituisce i byte della parte. HTTP 413 con Part exceeds the 10 MB part size indica un blocco troppo grande. Le parti vuote sono rifiutate come Empty part data.
Per completare il caricamento, invia una richiesta POST a complete_url; il server traccia già le parti, quindi non serve un array di ETag del client. Se mancano delle parti, la risposta dice Only N of M parts uploaded. Upload remaining parts before completing. Interroga lo stato, invia i numeri mancanti e completa di nuovo. Non ripetere l’inizializzazione come operazione idempotente: apre un’altra sessione e nessuna intestazione Idempotency-Key protegge questo endpoint.
Scadenze, conflitti e recupero sicuro
GET /api/upload/{session_id}/status restituisce status, bytes_uploaded, uploaded_parts, part_size, total_parts, has_multipart e file_id. file_id è nullo fino al completamento. Se non ricevi la risposta finale, controlla prima questo endpoint: una sessione complete e il suo ID permettono di recuperare il file senza caricare un’altra versione.
Una sessione in attesa mai avviata può essere dismessa dopo 10 minuti senza attività. Le sessioni multipart avviate diventano idonee alla rimozione dopo 24 ore senza scritture ricevute; la pulizia non garantisce un’ora di scadenza esatta. Riavvia una sessione dismessa con una nuova inizializzazione e reinvia tutte le parti. Uno slot di concorrenza della credenziale abbandonato scade dopo 15 minuti senza rinnovo; le richieste delle parti rinnovano lo slot di un caricamento attivo.
| Errore | Soluzione |
|---|---|
403, You don't have upload permission in this workspace | Chiedi all’amministratore dello spazio di lavoro il permesso necessario o scegli una destinazione consentita. |
403, You don't have access to the upload page | Il ruolo deve consentire l’accesso alla pagina oltre al caricamento tramite REST. |
404, Destination folder not found | Verifica che l’ID appartenga allo spazio di lavoro e sia visibile; non sostituirlo con un nome. |
403, folder_locked | Risolvi il blocco della destinazione con un amministratore autorizzato prima di riprovare. |
400, File exceeds the … GB size limit for this workspace | Usa un file più piccolo o chiedi all’amministratore di cambiare la regola dello spazio di lavoro. |
| 413 per limite di dimensione della credenziale | Sostituisci la chiave solo se è autorizzato un limite maggiore; il server controlla anche i byte effettivamente ricevuti. |
400 con error_code: concurrent_upload_limit | Completa o annulla altri trasferimenti; esamina max_concurrent_uploads nella risposta. |
409, Upload session is already complete | Interroga lo stato e recupera l’ID del file archiviato. |
| 429 o 503 riprovabile | Rispetta Retry-After; conserva lo stato multipart e riprova le parti mancanti anziché aprire sessioni sostitutive parallele. |
I controlli su spazio, dimensione ed estensione, limiti per membro e caricamenti simultanei precedono la verifica della destinazione e della versione. Il completamento ricontrolla i limiti applicabili sui byte ricevuti, quindi l’esito positivo dell’inizializzazione non garantisce la riuscita finale.
Un caricamento con lo stesso nome può diventare una nuova versione di un file esistente se il tuo accesso lo consente; non sempre crea soltanto nuovi file. Per una sostituzione intenzionale invia file_id e l’ultimo expected_version osservato all’inizializzazione. Una versione non aggiornata produce 409 version_conflict; aggiorna e decidi se sostituire i dati più recenti. Usa un nome di prova univoco per evitare modifiche accidentali delle versioni. La regola max_versions dello spazio di lavoro può eliminare definitivamente oggetti delle versioni precedenti dopo una sostituzione riuscita; se assente, il valore predefinito è 10 versioni conservate. Salva prima le revisioni precedenti necessarie, senza presumere che ogni caricamento conservi una cronologia illimitata.
Per abbandonare una sessione non completata invia DELETE /api/upload/{session_id} con la stessa autorizzazione. La richiesta interrompe l’archiviazione parziale e dismette la sessione; sessioni assenti o fallite restituiscono ok: true con already_gone: true. Le sessioni completate restituiscono 409 e non vengono eliminate da questo endpoint. L’annullamento scarta i progressi non salvati; non annulla un file o una versione completati.
Per la PUT singola puoi inviare X-Dosya-Sha256 con esattamente 64 caratteri esadecimali dello SHA-256 atteso. Un digest corrispondente imposta hash_verified: true; una differenza restituisce 400 hash_mismatch con hash atteso e ricevuto. Senza intestazione, false significa che non è stato fornito un digest client, non che la verifica sia fallita. Il completamento multipart non offre la stessa garanzia sulla verifica dell’hash offerta dalla richiesta singola; se l’integrità è essenziale verifica separatamente i byte scaricati.
Tieni i token fuori dalle tracce di debug e conserva in modo sicuro i metadati della sessione. Un token perso non può essere recuperato dalla riga mascherata nell’elenco. Revoca credenziali compromesse; non inviare intestazioni di autorizzazione del caricamento all’assistenza.
Risultato previsto
Una sessione completata identifica un file archiviato nello spazio di lavoro e nella cartella scelti. Il numero di byte restituito riflette il corpo ricevuto; un file esistente con lo stesso nome può invece avere una nuova versione. Verifica ID, dimensione e versione prima di considerare riuscito il trasferimento.
Guide correlate
Ti è stata utile?
Caricamento delle valutazioni…
Quando voti, salviamo un cookie tecnico per un massimo di 180 giorni, così puoi cambiare la tua risposta.
Domande e risposte
Fai una domanda sui passaggi di questa guida. Le domande vengono revisionate prima della pubblicazione.
Non inserire dati dell’account, credenziali o file privati nelle domande pubbliche. Usa l’assistenza privata in questi casi.
Caricamento delle domande…
Accedi al tuo account dosya per fare una domanda.