Kaip įkelti metaduomenų failą naudojant „REST“ žiniatinklio paslaugą?

Turiu REST žiniatinklio paslaugą, kuri šiuo metu teikia šį URL:

http: // server / data / media

kur vartotojai gali POST naudoti šiuos JSON:

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

sukurti naujus medijos metaduomenis.

Dabar turiu atsisiųsti failą kartu su daugialypės terpės metaduomenimis. Koks yra geriausias būdas tai padaryti? Galėčiau pristatyti naują nuosavybę, vadinamą file ir base64, kad koduotų failą, bet man buvo įdomu, ar yra geresnis būdas.

Jis taip pat naudoja multipart/form-data , pvz., HTML formos siuntimą, tačiau naudoju „REST“ žiniatinklio paslaugą, ir noriu laikytis JSON, jei tai įmanoma.

181
15 окт. nustatė Daniel T. Oct 15. 2010-10-15 03:21 '10, 3:21, 2010-10-15 03:21
@ 5 atsakymai

Sutinku su Greg, kad dviejų etapų metodas yra pagrįstas sprendimas, tačiau norėčiau tai daryti atvirkščiai. Norėčiau daryti:

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

Jei norite sukurti metaduomenų įrašą ir grąžinti atsakymą, pavyzdžiui:

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

Tada klientas gali naudoti šį ContentUrl ir atlikti PUT su failo duomenimis.

Geriausia šio požiūrio dalis yra ta, kad kai jūsų serveris pradeda pasverti dideliais kiekiais duomenų, sugrįžęs URL gali tiesiog nukreipti į kitą serverį, turintį didelį kiekį / tūrį. Arba galite įdiegti tam tikrą aplinkraštį, jei kyla problema su pralaidumu.

142
15 окт. Atsakyti Darrel Miller 15 okt. 2010-10-15 04:26 '10 4:26 val. 2010-10-15 04:26

Tik todėl, kad JSON neapvyniokite viso užklausos korpuso, nereiškia, kad „RESTful“ nenaudoja kelių multipart/form-data kad paskelbtų ir JSON, ir failą (arba kelis failus) vienam prašymui:

 curl -F "metadata=<metadata.json" -F "file=@my-file.tar.gz" http://example.com/add-file 

serverio pusėje (naudojant Python kaip programavimo lingua franca čia):

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

Jei norite įkelti kelis failus, galite naudoti atskirus „formos laukus“ kiekvienam:

 curl -F "metadata=<metadata.json" -F "file1=@some-file.tar.gz" -F "file2=@some-other-file.tar.gz" http://example.com/add-file 

šiuo atveju serverio kodas turės request.args['file1'][0] ir request.args['file2'][0]

arba pakartotinai naudoti tą patį:

border=0
 curl -F "metadata=<metadata.json" -F "files=@some-file.tar.gz" -F "files=@some-other-file.tar.gz" http://example.com/add-file 

... šiuo atveju request.args['files'] yra tik 2 ilgio sąrašas.

arba iš tikrųjų perkelti kelis failus į vieną lauką vienu metu:

 curl -F "metadata=<metadata.json" -F "files=@some-file.tar.gz,some-other-file.tar.gz" http://example.com/add-file 

... šiuo atveju request.args['files'] bus eilutė su visais failais, kuriuos turėsite analizuoti patys - jūs nežinote, kaip tai padaryti, bet esu tikras, kad nėra sunku ar geriau naudoti ankstesnius metodus.

Skirtumas tarp @ ir < yra tas, kad @ sukelia failą prisijungti prie failo ir < prideda failo turinį kaip teksto lauką.

PS Tik todėl, kad naudoju curl kaip POST užklausų generavimo būdą, tai nereiškia, kad tiksliai tie patys HTTP užklausos negali būti siunčiamos iš programavimo kalbos, pvz., „Python“, arba naudojant bet kokį pakankamai galimą įrankį.

89
25 окт. Eriko Alliko atsakymas spalio 25 d 2012-10-25 23:15 '12, 23:15, 2012-10-25 23:15

Vienas iš būdų išspręsti šią problemą yra dviejų fazių procesas. Pirma, pats failas įkeliamas naudojant POST, kur serveris grąžina tam tikrą identifikatorių klientui (identifikatorius gali būti SHA1 failo turinys). Tada antrasis užklausa metaduomenis susieja su failo duomenimis:

 { "Name": "Test", "Latitude": 12.59817, "Longitude": 52.12873, "ContentID": "7a788f56fa49ae0ba5ebde780efe4d6a89b5db47" } 

Įtraukus bazinį64 duomenų failą, koduotą JSON užklausoje, perduodamų duomenų dydis padidės 33%. Tai gali arba negali būti svarbi, priklausomai nuo bendro failo dydžio.

Kitas būdas būtų naudoti POST neapdorotus duomenų failus, bet įtraukti bet kokius metaduomenis HTTP užklausos antraštėje. Tačiau tai šiek tiek atsilieka nuo pagrindinių REST operacijų ir gali būti nepatogesnė kai kurioms HTTP kliento bibliotekoms.

25
15 окт. atsakymas, kurį pateikė Greg Hewgill spalio 15 d 2010-10-15 03:36 '10, 03:36, 2010-10-15 03:36

Suprantu, kad tai yra labai senas klausimas, bet tikiuosi, kad tai padės kitam, kai aš suklupau šiam pranešimui, ieškodamas to paties dalyko. Turėjau panašią problemą, tik tai, kad mano metaduomenys buvo Guid ir int. Sprendimas yra tas pats. Jūs galite tiesiog padaryti reikiamą metaduomenų URL dalį.

POST priėmimo metodas „kontrolieriaus“ klasėje:

 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; } 

Tada bet kuriuo atveju registruokite maršrutus, WebApiConfig.Register (HttpConfiguration config) man šiuo atveju.

 config.Routes.MapHttpRoute( name: "FooController", routeTemplate: "api/{controller}/{name}/{latitude}/{longitude}", defaults: new { } ); 
9
25 февр. Greg Biles atsakymas vasario 25 d 2013-02-25 19:49 '13, 19:49 PM 2013-02-25 19:49

Jei jūsų failas ir jo metaduomenys sukuria vieną šaltinį, tai visiškai galima atsisiųsti jį kaip vieną užklausą. Mėginio užklausa:

 POST https://target.com/myresources/resourcename HTTP/1.1 Accept: application/json Content-Type: multipart/form-data; boundary=-----------------------------28947758029299 Host: target.com -------------------------------28947758029299 Content-Disposition: form-data; name="application/json" {"markers": [ { "point":new GLatLng(40.266044,-74.718479), "homeTeam":"Lawrence Library", "awayTeam":"LUGip", "markerImage":"images/red.png", "information": "Linux users group meets second Wednesday of each month.", "fixture":"Wednesday 7pm", "capacity":"", "previousScore":"" }, { "point":new GLatLng(40.211600,-74.695702), "homeTeam":"Hamilton Library", "awayTeam":"LUGip HW SIG", "markerImage":"images/white.png", "information": "Linux users can meet the first Tuesday of the month to work out harward and configuration issues.", "fixture":"Tuesday 7pm", "capacity":"", "tv":"" }, { "point":new GLatLng(40.294535,-74.682012), "homeTeam":"Applebees", "awayTeam":"After LUPip Mtg Spot", "markerImage":"images/newcastle.png", "information": "Some of us go there after the main LUGip meeting, drink brews, and talk.", "fixture":"Wednesday whenever", "capacity":"2 to 4 pints", "tv":"" }, ] } -------------------------------28947758029299 Content-Disposition: form-data; name="name"; filename="myfilename.pdf" Content-Type: application/octet-stream %PDF-1.4 % 2 0 obj <</Length 57/Filter/FlateDecode>>stream x+r 26S00SI2P0Qn F !i\ )%!Y0i@.k [ endstream endobj 4 0 obj <</Type/Page/MediaBox[0 0 595 842]/Resources<</Font<</F1 1 0 R>>>>/Contents 2 0 R/Parent 3 0 R>> endobj 1 0 obj <</Type/Font/Subtype/Type1/BaseFont/Helvetica/Encoding/WinAnsiEncoding>> endobj 3 0 obj <</Type/Pages/Count 1/Kids[4 0 R]>> endobj 5 0 obj <</Type/Catalog/Pages 3 0 R>> endobj 6 0 obj <</Producer(iTextSharp 5.5.11 2000-2017 iText Group NV \(AGPL-version\))/CreationDate(D:20170630120636+02'00')/ModDate(D:20170630120636+02'00')>> endobj xref 0 7 0000000000 65535 f 0000000250 00000 n 0000000015 00000 n 0000000338 00000 n 0000000138 00000 n 0000000389 00000 n 0000000434 00000 n trailer <</Size 7/Root 5 0 R/Info 6 0 R/ID [<c7c34272c2e618698de73f4e1a65a1b5><c7c34272c2e618698de73f4e1a65a1b5>]>> %iText-5.5.11 startxref 597 %%EOF -------------------------------28947758029299-- 
1
30 июня '17 в 13:25 2017-06-30 13:25 Atsakymą davė Mike birželio 30 d. 17, 13:25 2017-06-30 13:25

Kiti klausimai apie „ žymas arba „ Klauskite“