Dosyayı və əlaqəli məlumatları RESTful WebService-ə göndərmək, tercihen JSON şəklində yerləşdirmək

Yəqin ki, axmaq bir sual olacaq, amma bu gecələrdən biri var. Ərizədə RESTful API hazırlayıram və müştərinin məlumatları JSON olaraq göndərməsini istəyirik. Bu proqramın bir hissəsi müştəri üçün bir fayl (adətən bir şəkil), eləcə də şəkil haqqında məlumatı yükləməsini tələb edir.

Tək istəklə necə baş verdiyini izləmək çətin olur. Bir json simvolunda bazlı 64 fayl məlumatı mümkündürmü? Serverə 2 mesaj göndərməyimə ehtiyac varmı? Bunun üçün JSON istifadə etməliyəmmi?

Bir yan qeyd olaraq, backend istifadə Grails və yerli mobil müştərilər (iPhone, Android, və s.) Bu vacibdir, bu xidmətləri əldə.

555
03 нояб. Gregg tərəfindən təyin 03 Noyabr. 2010-11-03 05:07 '10 saat 05:07 'da 2010-11-03 05:07
@ 11 cavab

Bənzər bir sual soruşdum:

REST veb xidmətindən istifadə edərək metadata faylını necə yükləmək olar?

Əsasən üç variant var:

  • Base64 məlumatın ölçüsünü təxminən 33% artıraraq faylı kodlaşdırır.
  • Faylı əvvəlcə multipart/form-data POST multipart/form-data a göndərin və identifikatoru müştəriyə qaytarın. Müştəri sonra metadata identifikator ilə göndərir və server fayl və meta məlumatları yenidən birləşdirir.
  • Öncelikle metadata göndərin və ID'yi müştəriye qaytarın. Müştəri sonra faylı identifikatorla göndərir və server fayl və metadata yenidən birləşir.
466
03 нояб. Cavab Daniel T tərəfindən verilir. 03 noyabr. 2010-11-03 05:59 '10 at 5:59 2010-11-03 05:59

Content type multipart / form-data istifadə edərək, bir sorğu üçün bir fayl və məlumat göndərə bilərsiniz:

Bir çox tətbiqdə istifadəçi bir forma verilə bilər. İstifadəçi, istifadəçi daxilində yaradılan və ya istifadəçi seçdiyi fayllardan daxil olan məlumatları daxil edən bir forma doldurur. Forma başa çatdıqdan sonra, formadan olan məlumatlar istifadəçidən alınan ərizə göndərilir.

MultiPart / Form-Data anlayışı bu tətbiqlərdən birinə gəlir ...

Http://www.faqs.org/rfcs/rfc2388.html ünvanından :

border=0

"multipart / form-data" bir neçə hissədən ibarətdir. Hər bir hissədə yerləşdirmə tipi "form-data" olduğu və yerin (optional) adı parametresini ehtiva etdiyi, bu parametrenin dəyəri formada olan sahənin orijinal adı olduğu Content-disposition başlığı [RFC 2183] . Məsələn, bir hissə başlığı ehtiva edə bilər:

Content-Disposition: form-data; adı = "istifadəçi"

"istifadəçi" giriş sahəsinə uyğun olan dəyəri ilə.

Sərhədlər arasındakı hər bölmədə fayl məlumatını və ya sahə məlumatını əlavə edə bilərsiniz. RESTful xidmətini müvəffəqiyyətlə həyata keçirmişəm ki, istifadəçi həm məlumatları, həm də formaları göndərməyi tələb etmiş və çoxpart / form-data yaxşı işləmişdir. Xidmət Java / Spring istifadə edərək qurulmuşdur və müştəri C # istifadə edir, təəssüf ki, mənim xidməti necə konfiqurasiya edəcəyinizi sizə izah edən Grails nümunələri yoxdur. Bu halda, hər bir "form-data" bölməsində parametr adı və onun dəyərini təyin etmək üçün bir yer təmin edildiyi üçün, JSON istifadə etmək lazım deyil.

Multipart / form-data istifadə etməyiniz yaxşı bir şeydir ki, HTTP-nin xüsusi başlıqlarını istifadə edirsiniz, belə ki xidmətinizi yaratmaq üçün mövcud HTTP vasitələrindən istifadə etməklə REST fəlsəfəsini təqib edirsiniz.

75
03 нояб. Cavab 03 noyabr tarixində McStretch tərəfindən verilir. 2010-11-03 05:49 '10 at 5:49 AM 2010-11-03 05:49

Bilirəm ki, bu filial olduqca qoca, amma burada bir variant yoxdur. Yüklənəcək məlumatlarla yanaşı göndərmək istədiyiniz metadata (hər hansı formatda) varsa, bir çox multipart/related sorğu göndərə bilərsiniz.

Multipart / Müvafiq media növü bədən bir neçə əlaqəli hissələrdən ibarət tərkibli obyektlər üçün nəzərdə tutulmuşdur.

Daha ətraflı məlumat üçün RFC 2387-ni kontrol edə bilərsiniz.

Əsasən, belə bir sorğunun hər bir hissəsi fərqli bir məzmuna sahib ola bilər və bütün hissələr (məsələn, bir şəkil və onun metadatası) bir-birinə bağlıdır. Parçalar bir sərhəd xətti ilə göstərilir və iki sərhəd son sərhəd xəttini təqib edir.

Məsələn:

 POST /upload HTTP/1.1 Host: www.hostname.com Content-Type: multipart/related; boundary=xyz Content-Length: [actual-content-length] --xyz Content-Type: application/json; charset=UTF-8 { "name": "Sample image", "desc": "...", ... } --xyz Content-Type: image/jpeg [image data] [image data] [image data] ... --foo_bar_baz-- 
32
23 мая '16 в 18:03 2016-05-23 18:03 cavab 23 may, 23 saat 18:03 2016-05-23 18:03 tarixində veriləcək

Mən bu sualın köhnə olduğunu bilirəm, amma son günlərdə bütün şəbəkəni bu məsələni həll etmək üçün aradım. Mən şəkillər, başlıq və təsvirləri göndərən REST və iPhone Client veb xidmətləri təqdim edirəm.

Mənim yanaşma ən yaxşısıdır, amma sadə və sadədirmi bilmirəm.

UIImagePickerController istifadə edərək anlık görüntü çəkirəm və şəkil məlumatlarını göndərmək üçün istək başlığı etiketlərini istifadə edərək NSData serverinə göndərirəm.

 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: error:> 

Server tərəfində kodu istifadə edərək bir şəkil alıram:

 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") } 

Gələcəkdə problemim varmı bilmirəm amma indi iş mühitində gözəl işləyir.

10
31 янв. Cavab Rscorreia Jan 31 tərəfindən verilir 2012-01-31 20:49 '12 at 20:49 PM 2012-01-31 20:49

Burada mənim API yanaşma (nümunəni istifadə edirəm) - görə bildiyiniz kimi, API-də file_id (serverda yüklənə bilən fayl identifikatorunu) istifadə etmirəm:

1. Serverda 'şəkil' obyekti yaradın:

 POST: /projects/{project_id}/photos params in: {name:some_schema.jpg, comment:blah} return: photo_id 

2. Faylı yükləyin ("fayl" tək şəklində olduğuna diqqət yetirin, çünki şəkil başına yalnız birdir):

 POST: /projects/{project_id}/photos/{photo_id}/file params in: file to upload return: - 

Və sonra, məsələn:

3.Müəlliflərin siyahısını oxuyun

 GET: /projects/{project_id}/photos params in: - return: array of objects: [ photo, photo, photo, ... ] 

4.Müxtəlif şəkillər haqqında ətraflı məlumat

 GET: /projects/{project_id}/photos/{photo_id} params in: - return: photo = { id: 666, name:'some_schema.jpg', comment:'blah'} 

5. Şəkil faylını oxuyun

 GET: /projects/{project_id}/photos/{photo_id}/file params in: - return: file content 

Beləliklə, nəticə əvvəlcə bir POST obyekti (şəkil) yaratdığınızdan sonra fayl ilə bir secod sorğu göndərməkdir (POST yenidən).

6
10 июля '16 в 23:31 2016-07-10 23:31 Cavab Kamil Kiełczewski tərəfindən 10 İyul, '16 'də 23:31 2016-07-10 23:31' də verilir

FormData obyektləri: Ajax ilə faylları yükləyin

XMLHttpRequest Səviyyə 2 yeni FormData interfeysinə dəstək verir. FormData obyektləri asanlıqla XMLHttpRequest send () metodu istifadə edərək asanlıqla göndərilə biləcək forma sahələri və onların dəyərlərini təmsil edən əsas / dəyər cütlərinin bir dəstini asanlıqla yaratmağı təmin edir.

 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

5
04 июля '14 в 12:07 2014-07-04 12:07 Cavab lakhan_Ideavate verilir 04 iyul '14 'də 12:07 2014-07-04 12:07

Yalnız eksik nümunə ANDROID nümunəsi olduğundan, onu əlavə edəcəyəm. Bu metod, Aktivlik sinifində elan edilməli olan xüsusi bir AsyncTask istifadə edir.

 private class UploadFile extends AsyncTask<Void, Integer, String> { @Override protected void onPreExecute() { // set a status bar or show a dialog to the user here super.onPreExecute(); } @Override protected void onProgressUpdate(Integer... progress) { // progress[0] is the current status (eg 10%) // here you can update the user interface with the current status } @Override protected String doInBackground(Void... params) { return uploadFile(); } private String uploadFile() { String responseString = null; HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("http://example.com/upload-file"); try { AndroidMultiPartEntity ampEntity = new AndroidMultiPartEntity( new ProgressListener() { @Override public void transferred(long num) { // this trigger the progressUpdate event publishProgress((int) ((num / (float) totalSize) * 100)); } }); File myFile = new File("/my/image/path/example.jpg"); ampEntity.addPart("fileFieldName", new FileBody(myFile)); totalSize = ampEntity.getContentLength(); httpPost.setEntity(ampEntity); // Making server call HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode == 200) { responseString = EntityUtils.toString(httpEntity); } else { responseString = "Error, http status: " + statusCode; } } catch (Exception e) { responseString = e.getMessage(); } return responseString; } @Override protected void onPostExecute(String result) { // if you want update the user interface with upload result super.onPostExecute(result); } } 

Beləliklə, faylınızı yükləmək istədiyiniz zaman, sadəcə:

 new UploadFile().execute(); 
4
13 сент. Cavab lifeisfoo tərəfindən verilib 13 sentyabr. 2015-09-13 12:40 '15 saat 12:40 'də 2015-09-13 12:40
 @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 } 
0
30 марта '15 в 12:47 2015-03-30 12:47 Cavab günəş enerjisi verilir 30 Mart 2015 12:47 2015-03-30 12:47

Serverə bir neçə xətt göndərmək lazımdır. Json və multipart istifadə etmədi, sorğu parametrlərini istifadə etdim.

 @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 belə görünür:

 http://localhost:8080/file/upload?uuid=46f073d0> 

Faylların yüklənməsi ilə birlikdə iki parametr (uuid və növü) keçir. Ümid edirəm ki, bu göndərmək üçün heç bir mürəkkəb olmayan json məlumatı olmayanlara kömək edir.

0
01 сент. Cavab Aslam anwer 01 Sentyabr verilir. 2018-09-01 17:08 '18 saat 17:08 'da 2018-09-01 17:08

Tətil serverini inkişaf etdirirsinizsə, bunu edə bilərsiniz

  • Müştərinin HTTP vasitəsilə fayldan soruşması
  • Müştəri daha sonra URL'yi json verilerinizle göndərə bilər, məsələn, şəkil faylı {"file_url":"http://cockwombles.com/blah.jpg"}
  • Server daha sonra faylı yükləyə bilər.
-4
17 марта '17 в 17:20 2017-03-17 17:20 Cümə namazının cavabını 17 Mart 17:20 'də verən 2017-03-17 17:20

Aşağıdakı idxal olduğundan əmin olun. Əlbəttə ki, digər standart idxal olunan mallar

 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 } 
-5
10 окт. 10 oktyabrda Mak Kul tərəfindən verilmiş cavab . 2015-10-10 17:54 '15 'da 17:54' de, 2015-10-10 17:54

əlaqədar digər suallar və ya sual