Mam usługę sieci Web REST, która obecnie udostępnia ten adres URL:
http: // serwer / dane / media
gdzie użytkownicy mogą wykonać POST
następujący JSON:
{
"Name": "Test",
"Latitude": 12.59817,
"Longitude": 52.12873
}
w celu utworzenia nowych metadanych mediów.
Teraz potrzebuję możliwości przesłania pliku w tym samym czasie, co metadane multimedialne. Jak najlepiej to zrobić? Mógłbym wprowadzić nową właściwość o nazwie file
i kodowanie base64 pliku, ale zastanawiałem się, czy istnieje lepszy sposób.
Jest też multipart/form-data
coś w rodzaju wysyłania formularza HTML, ale korzystam z usługi internetowej REST i chcę w miarę możliwości trzymać się JSON.
web-services
json
rest
file-upload
Daniel T.
źródło
źródło
Odpowiedzi:
Zgadzam się z Gregiem, że podejście dwufazowe jest rozsądnym rozwiązaniem, ale zrobiłbym to na odwrót. Chciałbym zrobić:
Aby utworzyć pozycję metadanych i zwrócić odpowiedź, taką jak:
Klient może następnie użyć tego ContentUrl i wykonać PUT z danymi pliku.
Zaletą tego podejścia jest to, że kiedy serwer zaczyna obciążać się ogromnymi ilościami danych, zwracany adres URL może po prostu wskazywać inny serwer z większą przestrzenią / pojemnością. Lub możesz zastosować jakieś okrągłe podejście robin, jeśli problem stanowi przepustowość.
źródło
To, że nie pakujesz całego ciała żądania w JSON, nie oznacza, że RESTful nie może używać
multipart/form-data
zarówno JSON, jak i plików w jednym żądaniu:po stronie serwera (używając Pythona dla pseudokodu):
aby przesłać wiele plików, można użyć osobnych „pól formularza” dla każdego:
... w takim przypadku kod serwera będzie miał
request.args['file1'][0]
irequest.args['file2'][0]
lub użyj tego samego dla wielu:
... w takim przypadku
request.args['files']
będzie to po prostu lista długości 2.lub prześlij wiele plików przez jedno pole:
...w którym to przypadku
request.args['files']
będzie ciąg znaków zawierający wszystkie pliki, które będziesz musiał sam przeanalizować - nie wiem, jak to zrobić, ale jestem pewien, że nie jest to trudne, albo lepiej po prostu użyj poprzednich podejść.Różnica między
@
i<
polega na tym,@
że plik zostaje dołączony jako przesyłany plik, a<
zawartość pliku jest dołączana jako pole tekstowe.PS To, że używam
curl
jako sposobu generowaniaPOST
żądań, nie oznacza, że dokładnie takie same żądania HTTP nie mogą być wysyłane z języka programowania, takiego jak Python, ani za pomocą jakiegokolwiek wystarczająco sprawnego narzędzia.źródło
curl -f 'metadata={"foo": "bar"}'
?Jednym ze sposobów rozwiązania tego problemu jest uczynienie przesyłania dwufazowym procesem. Najpierw sam prześlesz plik za pomocą testu POST, w którym serwer zwraca klientowi pewien identyfikator (identyfikatorem może być SHA1 zawartości pliku). Następnie drugie żądanie wiąże metadane z danymi pliku:
Włączenie pliku bazy danych64 zakodowanego w samym żądaniu JSON zwiększy rozmiar przesyłanych danych o 33%. To może, ale nie musi być ważne, w zależności od ogólnego rozmiaru pliku.
Innym podejściem może być użycie testu POST nieprzetworzonych danych pliku, ale dołączenie dowolnych metadanych do nagłówka żądania HTTP. Jest to jednak nieco poza podstawowymi operacjami REST i może być bardziej niezręczne w przypadku niektórych bibliotek klienta HTTP.
źródło
Zdaję sobie sprawę, że to bardzo stare pytanie, ale mam nadzieję, że pomoże to komuś innemu, gdy natknąłem się na ten post w poszukiwaniu tego samego. Miałem podobny problem, tyle że moje metadane to Guid i int. Rozwiązanie jest takie samo. Możesz po prostu uczynić potrzebne metadane częścią adresu URL.
Metoda akceptacji POST w twojej klasie „Controller”:
Następnie, niezależnie od tego, co rejestrujesz trasy, w tym przypadku dla mnie WebApiConfig.Register (konfiguracja HttpConfiguration).
źródło
Jeśli Twój plik i jego metadane tworzą jeden zasób, możesz przesłać je oba w jednym żądaniu. Przykładowe żądanie będzie:
źródło
Nie rozumiem, dlaczego w ciągu ośmiu lat nikt nie opublikował łatwej odpowiedzi. Zamiast zakodować plik jako base64, zakoduj plik json jako ciąg. Następnie po prostu odkoduj json po stronie serwera.
W JavaScript:
POST to używając Content-Type: multipart / form-data
Po stronie serwera pobierz plik normalnie i pobierz plik json jako ciąg. Konwertuj ciąg znaków na obiekt, który zwykle stanowi jeden wiersz kodu, bez względu na używany język programowania.
(Tak, działa świetnie. Robię to w jednej z moich aplikacji).
źródło