servizi - Pubblicazione di un file e dei dati associati a un WebService RESTful preferibilmente come JSON




web service rest esempio (8)

È possibile inviare il file e i dati in un'unica richiesta utilizzando il tipo di contenuto multipart/form-data :

In molte applicazioni, è possibile che un utente venga presentato con un modulo. L'utente compilerà il modulo, comprese le informazioni che sono state digitate, generate dall'input dell'utente o incluse dai file selezionati dall'utente. Quando il modulo viene compilato, i dati del modulo vengono inviati dall'utente all'applicazione ricevente.

La definizione di MultiPart / Form-Data deriva da una di quelle applicazioni ...

Da http://www.faqs.org/rfcs/rfc2388.html :

"multipart / form-data" contiene una serie di parti. Ci si aspetta che ogni parte contenga un'intestazione content-disposition [RFC 2183] dove il tipo di disposizione è "form-data" e dove la disposizione contiene un parametro (aggiuntivo) di "nome", dove il valore di tale parametro è l'originale nome del campo nel modulo. Ad esempio, una parte potrebbe contenere un'intestazione:

Content-Disposition: form-data; name = "utente"

con il valore corrispondente alla voce del campo "utente".

È possibile includere informazioni sui file o informazioni sul campo all'interno di ciascuna sezione tra i limiti. Ho implementato con successo un servizio RESTful che richiedeva all'utente di inviare sia dati che un modulo, e dati multiparte / moduli funzionavano perfettamente. Il servizio è stato realizzato utilizzando Java / Spring e il client utilizzava C #, quindi sfortunatamente non ho esempi Grails da darti riguardo a come configurare il servizio. In questo caso non è necessario utilizzare JSON poiché ogni sezione "dati-modulo" fornisce una posizione per specificare il nome del parametro e il relativo valore.

L'aspetto positivo dell'utilizzo di multipart / form-data è che stai usando intestazioni definite da HTTP, quindi ti stai attenendo alla filosofia REST di utilizzare gli strumenti HTTP esistenti per creare il tuo servizio.

Questa sarà probabilmente una domanda stupida, ma sto vivendo una di quelle notti. In un'applicazione sto sviluppando API RESTful e vogliamo che il client invii i dati come JSON. Parte di questa applicazione richiede al client di caricare un file (solitamente un'immagine) e informazioni sull'immagine.

Sto avendo difficoltà a rintracciare come ciò avviene in una singola richiesta. E 'possibile Base64 i dati del file in una stringa JSON? Avrò bisogno di eseguire 2 messaggi sul server? Non dovrei usare JSON per questo?

Come nota a margine, stiamo utilizzando Grails sul back-end e questi servizi sono accessibili da client mobili nativi (iPhone, Android, ecc.), Se qualcuna di queste cose fa la differenza.


Assicurati di aver seguito l'importazione. Ofcourse altre importazioni standard

import org.springframework.core.io.FileSystemResource


    void uploadzipFiles(String token) {

        RestBuilder rest = new RestBuilder(connectTimeout:10000, readTimeout:20000)

        def zipFile = new File("testdata.zip")
        def Id = "001G00000"
        MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>()
        form.add("id", id)
        form.add('file',new FileSystemResource(zipFile))
        def urld ='''http://URL''';
        def resp = rest.post(urld) {
            header('X-Auth-Token', clientSecret)
            contentType "multipart/form-data"
            body(form)
        }
        println "resp::"+resp
        println "resp::"+resp.text
        println "resp::"+resp.headers
        println "resp::"+resp.body
        println "resp::"+resp.status
    }

Ho fatto una domanda simile qui:

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

Fondamentalmente hai tre scelte:

  1. Base64 codifica il file, a spese di aumentare la dimensione dei dati di circa il 33%.
  2. Invia il file prima in un POST multipart/form-data e restituisci un ID al client. Il client invia quindi i metadati con l'ID e il server riassocia il file e i metadati.
  3. Invia prima i metadati e restituisci un ID al client. Il client invia quindi il file con l'ID e il server riassocia il file e i metadati.

Oggetti FormData: carica i file usando Ajax

XMLHttpRequest Level 2 aggiunge il supporto per la nuova interfaccia FormData. Gli oggetti FormData consentono di creare facilmente un insieme di coppie chiave / valore che rappresentano i campi modulo e i relativi valori, che possono quindi essere facilmente inviati utilizzando il metodo XMLHttpRequest send ().

function AjaxFileUpload() {
    var file = document.getElementById("files");
    //var file = fileInput;
    var fd = new FormData();
    fd.append("imageFileData", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", '/ws/fileUpload.do');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
             alert('error');
    };
    xhr.send(fd);
}

https://developer.mozilla.org/en-US/docs/Web/API/FormData


Se stai sviluppando un server di riposo puoi farlo

  1. Chiedi al client di esporre il file su HTTP
  2. Il cliente può quindi inviare l'url con i tuoi dati json ad esempio un file di immagine {"file_url":"http://cockwombles.com/blah.jpg"}
  3. Il server può quindi scaricare il file.

So che questa domanda è vecchia, ma negli ultimi giorni avevo cercato in tutta la rete di risolvere la stessa domanda. Ho grails REST webservices e iPhone Client che inviano foto, titolo e descrizione.

Non so se il mio approccio è il migliore, ma è così facile e semplice.

Scatto una foto utilizzando UIImagePickerController e invii al server NSData utilizzando i tag di intestazione della richiesta per inviare i dati dell'immagine.

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"myServerAddress"]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:UIImageJPEGRepresentation(picture, 0.5)];
[request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"myPhotoTitle" forHTTPHeaderField:@"Photo-Title"];
[request setValue:@"myPhotoDescription" forHTTPHeaderField:@"Photo-Description"];

NSURLResponse *response;

NSError *error;

[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

Sul lato server, ricevo la foto utilizzando il codice:

InputStream is = request.inputStream

def receivedPhotoFile = (IOUtils.toByteArray(is))

def photo = new Photo()
photo.photoFile = receivedPhotoFile //photoFile is a transient attribute
photo.title = request.getHeader("Photo-Title")
photo.description = request.getHeader("Photo-Description")
photo.imageURL = "temp"    

if (photo.save()) {    

    File saveLocation = grailsAttributes.getApplicationContext().getResource(File.separator + "images").getFile()
    saveLocation.mkdirs()

    File tempFile = File.createTempFile("photo", ".jpg", saveLocation)

    photo.imageURL = saveLocation.getName() + "/" + tempFile.getName()

    tempFile.append(photo.photoFile);

} else {

    println("Error")

}

Non so se avrò problemi in futuro, ma ora sta funzionando bene nell'ambiente di produzione.


Volevo inviare alcune stringhe al server di back-end. Non ho usato json con multipart, ho usato i parametri di richiesta.

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public void uploadFile(HttpServletRequest request,
        HttpServletResponse response, @RequestParam("uuid") String uuid,
        @RequestParam("type") DocType type,
        @RequestParam("file") MultipartFile uploadfile)

Url sarebbe simile

http://localhost:8080/file/upload?uuid=46f073d0&type=PASSPORT

Sto passando due parametri (uuid e type) insieme al caricamento del file. Spero che questo aiuti chi non ha i dati complessi di JSON da inviare.


@RequestMapping(value = "/uploadImageJson", method = RequestMethod.POST)
    public @ResponseBody Object jsongStrImage(@RequestParam(value="image") MultipartFile image, @RequestParam String jsonStr) {
-- use  com.fasterxml.jackson.databind.ObjectMapper convert Json String to Object
}




file-upload