json - rest api receiving file




API REST-elaborazione di file(ovvero immagini)-migliori pratiche (3)

La tua seconda soluzione è probabilmente la più corretta. È necessario utilizzare le specifiche HTTP e i mimetipi nel modo in cui erano previsti e caricare il file tramite multipart/form-data . Per quanto riguarda la gestione delle relazioni, utilizzerei questo processo (tenendo presente che non conosco nulla dei tuoi presupposti o della progettazione del sistema):

  1. POST /users per creare l'entità utente.
  2. POST l'immagine su /images , assicurandosi di riportare un'intestazione Location in cui l'immagine può essere recuperata secondo le specifiche HTTP.
  3. PATCH a /users/carPhoto e /users/carPhoto l'ID della foto indicato nell'intestazione Location del passaggio 2.

Stiamo sviluppando un server con API REST, che accetta e risponde con JSON. Il problema è, se è necessario caricare immagini dal client al server.

Si noti inoltre che sto parlando di use-case, in cui l'entità (utente) può avere file (carPhoto, licensePhoto) e anche altre proprietà (nome, e-mail ...), ma quando si crea un nuovo utente, non si inviano queste immagini , vengono aggiunti dopo il processo di registrazione.

Le soluzioni di cui sono a conoscenza, ma ognuna di esse presenta alcuni difetti

1. Utilizzare multipart / form-data anziché JSON

buono : le richieste POST e PUT sono il più RESTful possibile, possono contenere input di testo insieme al file.

contro : Non è più JSON, che è molto più facile da testare, eseguire il debug, ecc. rispetto ai dati multipart / form

2. Consentire di aggiornare file separati

La richiesta POST per la creazione di un nuovo utente non consente di aggiungere immagini (il che è ok nel nostro caso d'uso come ho detto all'inizio), il caricamento delle foto viene effettuato dalla richiesta PUT come multipart / form-data ad esempio / users / 4 / carPhoto

buono : tutto (tranne il caricamento del file stesso) rimane in JSON, è facile da testare ed eseguire il debug (puoi registrare richieste JSON complete senza aver paura della loro lunghezza)

contro : non è intuitivo, non puoi POST o PUT tutte le variabili di entità contemporaneamente e anche questo indirizzo /users/4/carPhoto possono essere considerate più come una raccolta (il caso d'uso standard per l'API REST è simile a questo /users/4/shipments ). Di solito non puoi (e non vuoi) OTTENERE / METTERE ogni variabile di entità, ad esempio utenti / 4 / nome. Puoi ottenere il nome con GET e modificarlo con PUT su users / 4. Se c'è qualcosa dopo l'id, di solito è un'altra raccolta, come utenti / 4 / recensioni

3. Utilizzare Base64

Invialo come JSON ma codifica i file con Base64.

buono : come la prima soluzione, è il servizio RESTful possibile.

contro : Ancora una volta, i test e il debug sono molto peggiori (il corpo può avere megabyte di dati), c'è un aumento delle dimensioni e anche dei tempi di elaborazione sia in client che in server

Vorrei davvero usare la soluzione no. 2, ma ha i suoi contro ... Chiunque può darmi una visione migliore della soluzione "qual è la migliore"?

Il mio obiettivo è avere servizi RESTful con il maggior numero possibile di standard inclusi, mentre voglio renderlo il più semplice possibile.


Non esiste una soluzione facile. Ogni modo ha i suoi pro e contro. Ma il modo canonico sta usando la prima opzione: multipart/form-data . Come dice la guida alle raccomandazioni W3

Il tipo di contenuto "multipart / form-data" deve essere utilizzato per l'invio di moduli che contengono file, dati non ASCII e dati binari.

In realtà non stiamo inviando moduli, ma si applica ancora il principio implicito. L'uso di base64 come rappresentazione binaria non è corretto perché stai utilizzando lo strumento errato per raggiungere il tuo obiettivo, d'altra parte, la seconda opzione obbliga i tuoi client API a fare più lavoro per consumare il tuo servizio API. Dovresti fare il duro lavoro sul lato server per fornire un'API di facile utilizzo. La prima opzione non è facile da eseguire il debug, ma quando lo fai, probabilmente non cambia mai.

Usando multipart/form-data sei fedele alla filosofia REST / http. Puoi visualizzare una risposta a una domanda simile here .

Un'altra opzione se si mescolano le alternative, è possibile utilizzare multipart / form-data ma invece di inviare ogni valore separatamente, è possibile inviare un valore denominato payload con il payload json al suo interno. (Ho provato questo approccio usando ASP.NET WebAPI 2 e funziona benissimo).


OP qui (sto rispondendo a questa domanda dopo due anni, il post di Daniel Cerecedo non è stato male alla volta, ma i servizi web si stanno sviluppando molto velocemente)

Dopo tre anni di sviluppo software a tempo pieno (con particolare attenzione anche all'architettura software, alla gestione dei progetti e all'architettura dei microservizi), scelgo sicuramente il secondo modo (ma con un endpoint generale) come il migliore.

Se hai un endpoint speciale per le immagini, ti dà molto più potere sulla gestione di quelle immagini.

Abbiamo la stessa API REST (Node.js) sia per le app mobili (iOS / Android) sia per il frontend (usando React). Questo è il 2017, quindi non vuoi archiviare le immagini localmente, vuoi caricarle su un po 'di cloud storage (Google cloud, s3, cloudinary, ...), quindi vuoi una gestione generale su di esse.

Il nostro flusso tipico è che non appena si seleziona un'immagine, inizia a caricarsi sullo sfondo (di solito POST su / endpoint immagini), restituendo l'ID dopo il caricamento. Questo è davvero facile da usare, perché l'utente sceglie un'immagine e quindi in genere procede con alcuni altri campi (ad esempio indirizzo, nome, ...), quindi quando preme il pulsante "invia", l'immagine è di solito già caricata. Non aspetta e guarda lo schermo che dice "caricamento in corso ...".

Lo stesso vale per ottenere immagini. Soprattutto grazie ai telefoni cellulari e ai dati mobili limitati, non vuoi inviare immagini originali, vuoi inviare immagini ridimensionate, quindi non occupano molta larghezza di banda (e per rendere le tue app mobili più veloci, spesso non vuoi per ridimensionarlo, vuoi l'immagine che si adatta perfettamente alla tua vista). Per questo motivo, le buone app stanno usando qualcosa come cloudinary (o abbiamo il nostro server di immagini per il ridimensionamento).

Inoltre, se i dati non sono privati, ti rispedisci all'URL dell'app / frontend e li scarica direttamente dal cloud storage, il che significa enorme risparmio di larghezza di banda e tempo di elaborazione per il tuo server. Nelle nostre app più grandi ci sono molti terabyte scaricati ogni mese, non vuoi gestirlo direttamente su ciascuno dei tuoi server API REST, che è focalizzato sull'operazione CRUD. Vuoi gestirlo in un unico posto (il nostro Imageserver, che ha la cache ecc.) O lasciare che i servizi cloud lo gestiscano.

Contro: L'unico "contro" a cui dovresti pensare è "non immagini assegnate". L'utente seleziona le immagini e continua a compilare altri campi, ma poi dice "nah" e disattiva l'app o la scheda, ma nel frattempo hai caricato correttamente l'immagine. Ciò significa che hai caricato un'immagine che non è stata assegnata da nessuna parte.

Esistono diversi modi per gestirlo. Il più semplice è "Non mi interessa", che è rilevante, se ciò non accade molto spesso o hai persino il desiderio di memorizzare ogni immagine che l'utente ti invia (per qualsiasi motivo) e non vuoi eliminazione.

Anche un altro è facile: hai CRON e cioè ogni settimana e cancelli tutte le immagini non assegnate più vecchie di una settimana.





restful-architecture