2012-09-04 15 views
14

Possiedo un metodo ASP.NET MVC 4 Web Api controller che riceve un elenco di ID file e restituisce le immagini di anteprima per tali file.Qual è il modo migliore per servire più file binari da un singolo metodo WebApi?

Quindi, il cliente potrebbe passare in un elenco di ID numerici (ad esempio, 10, 303, 29), e il metodo restituisce una lista in cui un ThumbnailImage sembra un po 'come questo:

class ThumbnailImage 
{ 
    public int Id { get; set; } 
    // Some other stuff 
    public byte[] RawData { get; set; } 
} 

La ragione per cui il chiamante passa in una lista di ID invece di fare una chiamata per articolo dovrebbe essere ovvio - potrebbero esserci decine o centinaia di articoli da scaricare, e sto cercando di evitare tutto il traffico HTTP che sarebbe necessario per scaricarli singolarmente .

Attualmente sto utilizzando RestSharp e JSON.NET e quindi i miei oggetti ThumbnailImage vengono passati attraverso il cavo come JSON. Va bene dal punto di vista della semplicità di codifica, ma JSON non è un modo efficace per rappresentare quei dati binari.

Quindi, sto pensando che dovrei restituire i byte grezzi come un flusso ottetto ... tuttavia, mentre posso farlo facilmente per una singola immagine, non sono sicuro del modo migliore per farlo per più immagini, specialmente quando devo anche restituire l'ID e altre informazioni varie per ogni file. (L'ID è richiesto poiché i risultati non verranno necessariamente restituiti in un determinato ordine e alcuni file potrebbero essere mancanti).

I potuto semplicemente scrivere tutto frammentario nel flusso di risposta, in modo che ogni voce scrivo l'ID (codificato), seguito dalla lunghezza dei dati di immagine, seguita dai dati dell'immagine stessa, e poi seguita per la stessa cosa per la voce successiva, ecc

il chiamante avrebbe poi semplicemente continuare a leggere dal flusso fino a quando non è stato esaurito, fare ipotesi circa la codifica (e la lunghezza!) degli ID, ecc

Penso che funzionerebbe, ma sembra clunky - c'è un modo migliore?

+0

Come sarà il client usa le immagini? le immagini per la visualizzazione in una pagina Web? o per il download come archivio? qualcos'altro? – EBarr

+0

Mi chiedo se è possibile inviare la risposta come MultipartContent in cui i contenuti interni potrebbero essere StreamContent con il flusso raw di byte –

+0

@EBarr: sto scrivendo anche l'applicazione client, quindi è un ambiente chiuso. Visualizzerò le immagini all'interno di un'applicazione WinForms (come miniature dei risultati di ricerca) –

risposta

10

OK, ecco uno snippet di codice che sembra funzionare, usando il MultipartContent a cui KiranChalla si riferiva.(Questo è solo un esempio fittizio che mostra come restituire due file di tipo diverso, in combinazione con un "oggetto" JSON-codificato (che in questo caso è solo un elenco di numeri interi ID).

public HttpResponseMessage Get() 
{ 
    var content = new MultipartContent(); 
    var ids = new List<int>() { 1, 2 }; 

    var objectContent = new ObjectContent<List<int>>(ids, new System.Net.Http.Formatting.JsonMediaTypeFormatter()); 
    content.Add(objectContent); 

    var file1Content = new StreamContent(new FileStream(@"c:\temp\desert.jpg", FileMode.Open)); 
    file1Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("image/jpeg"); 
    content.Add(file1Content); 

    var file2Content = new StreamContent(new FileStream(@"c:\temp\test.txt", FileMode.Open)); 
    file2Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("text/plain"); 
    content.Add(file2Content); 

    var response = new HttpResponseMessage(); 
    response.Content = content; 
    return response; 
} 
+2

non funziona per me. Restituisce solo un file che non è un formato valido. mi aiuti per favore. Ho bloccato con questo –

0

È possibile creare un file compresso (ad esempio un file ZIP) tra tutte le miniature e inviarlo di nuovo.

Quindi il chiamante deve solo decomprimerlo alla fine - l'invio di un singolo file contenente più file sarà molto più accettabile di inviare più file in un singolo flusso.

Lo svantaggio è che è meno probabile che sia in grado di sfruttare il caching (a seconda dei modelli di utilizzo, ovviamente).

+0

Ma poi ho ancora lo stesso problema (anche se in un altro posto) di passare tutte le informazioni correlate (es. L'ID) ... Inoltre, non vedo davvero perché è più facile decomprimere un ZIP di quanto lo sia decomprimere un flusso di file concatenato? –

+1

@GaryMcGill 'ZIP' è ampiamente implementato. Non si limita a comprimere, ma agisce anche come un formato di contenitore flessibile per più file. È possibile avere un "file" con informazioni correlate come primo file e utilizzare gli ID dei file effettivi come nomi di file. Se si utilizza la modalità di compressione 'Store' di ZIP, sarà effettivamente lo schema' nome, lunghezza, byte 'descritto nella domanda. –

1

Una sfida che vedo è che in base al numero di immagini inviate indietro il chiamante deve regolare il loro valore di timeout. Se questo fosse per un negozio di libri, potrebbero esserci molte immagini inviate indietro.

Cosa succede se si restituiscono gli URL solo per ogni immagine e si lascia al chiamante l'immagine effettiva? Significherebbe un po 'più di traffico con più chiamate, ma il chiamante otterrebbe le informazioni prima possibile e poi otterrà le immagini in base ai requisiti del chiamante.

Potrei sbagliarmi, ma ho pensato che l'idea alla base del resto era identificare ogni risorsa rispetto al raggruppamento di un gruppo di immagini e chiamare quella risorsa. Solo un pensiero ...

+0

Sono d'accordo: probabilmente non è molto RESTful per raggruppare le cose in questo modo, ma in realtà sto scrivendo anche l'applicazione (solo) che userà questo servizio web, quindi penso che sia OK. –

+1

Un buon punto sul valore di timeout, sebbene dal momento che sto scrivendo anche il client, posso anche occuparmene. (Probabilmente ne chiederò solo una o due alla volta). Penso che il traffico extra richiesto per inviare 100 immagini sia troppo da sopportare, e quindi ritenerle individualmente non mi sembra giusto. –

Problemi correlati