web-services - via - web service upload file java




Come carico un file con i metadati usando un servizio web REST? (4)

Mi rendo conto che questa è una domanda molto vecchia, ma spero che questo possa aiutare qualcun altro a uscire da questo post cercando la stessa cosa. Ho avuto un problema simile, solo che i miei metadati erano un Guid e int. La soluzione è la stessa però. Puoi semplicemente rendere la parte dei metadati necessaria per l'URL.

Metodo POST di accettazione nella tua classe "Controller":

public Task<HttpResponseMessage> PostFile(string name, float latitude, float longitude)
{
    //See http://stackoverflow.com/a/10327789/431906 for how to accept a file
    return null;
}

In questo caso, in qualsiasi percorso di registrazione, WebApiConfig.Register (HttpConfiguration config) è disponibile per me.

config.Routes.MapHttpRoute(
    name: "FooController",
    routeTemplate: "api/{controller}/{name}/{latitude}/{longitude}",
    defaults: new { }
);

Ho un servizio web REST che attualmente espone questo URL:

http://server/data/media

dove gli utenti possono POST il seguente JSON:

{
    "Name": "Test",
    "Latitude": 12.59817,
    "Longitude": 52.12873
}

per creare un nuovo metadato multimediale.

Ora ho bisogno della possibilità di caricare un file nello stesso momento dei metadati multimediali. Qual è il modo migliore di fare questo? Potrei introdurre una nuova proprietà chiamata file e base64 codificherà il file, ma mi chiedevo se ci fosse un modo migliore.

C'è anche l'uso di multipart/form-data come quello che manderebbe un modulo HTML, ma sto usando un servizio web REST e voglio attenermi all'utilizzo di JSON se possibile.



Solo perché non stai eseguendo il wrapping dell'intero corpo della richiesta in JSON, non significa che non sia RESTful utilizzare multipart/form-data per pubblicare sia il JSON che il file (o più file) in una singola richiesta:

curl -F "metadata=<metadata.json" -F "[email protected]" http://example.com/add-file

dal lato server (usando Python come linguaggio di programmazione qui):

class AddFileResource(Resource):
    def render_POST(self, request):
        metadata = json.loads(request.args['metadata'][0])
        file_body = request.args['file'][0]
        ...

per caricare più file, è possibile utilizzare "campi modulo" separati per ognuno:

curl -F "metadata=<metadata.json" -F "[email protected]" -F "[email protected]" http://example.com/add-file

... nel qual caso il codice del server avrà request.args['file1'][0] e request.args['file2'][0]

o riutilizzare lo stesso per molti:

curl -F "metadata=<metadata.json" -F "[email protected]" -F "[email protected]" http://example.com/add-file

... nel qual caso request.args['files'] sarà semplicemente un elenco di lunghezza 2.

o effettivamente passare più file in un unico campo in una volta sola:

curl -F "metadata=<metadata.json" -F "[email protected],some-other-file.tar.gz" http://example.com/add-file

... nel qual caso request.args['files'] sarà una stringa contenente tutti i file, che dovrai analizzare da solo - non sono sicuro di come farlo, ma sono sicuro che non è difficile, o meglio basta usare gli approcci precedenti.

La differenza tra @ e < è che @ fa sì che il file venga collegato come un caricamento di file, mentre < collega il contenuto del file come un campo di testo.

PS Solo perché sto usando curl come metodo per generare le richieste POST non significa che le stesse richieste HTTP non possano essere inviate da un linguaggio di programmazione come Python o usando uno strumento sufficientemente capace.


Sono d'accordo con Greg sul fatto che un approccio a due fasi sia una soluzione ragionevole, tuttavia lo farei al contrario. Farei:

POST http://server/data/media
body:
{
    "Name": "Test",
    "Latitude": 12.59817,
    "Longitude": 52.12873
}

Per creare la voce dei metadati e restituire una risposta come:

201 Created
Location: http://server/data/media/21323
{
    "Name": "Test",
    "Latitude": 12.59817,
    "Longitude": 52.12873,
    "ContentUrl": "http://server/data/media/21323/content"
}

Il client può quindi utilizzare questo ContentUrl e fare un PUT con i dati del file.

La cosa bella di questo approccio è quando il tuo server inizia ad essere appesantito con immensi volumi di dati, l'url che si restituisce può semplicemente puntare ad un altro server con più spazio / capacità. Oppure potresti implementare una sorta di approccio round robin se la larghezza di banda è un problema.







file-upload