ماهو - نشر ملف والبيانات المرتبطة إلى RESTful WebService ويفضل أن يكون JSON




json ماهو (7)

أعلم أن هذا السؤال قديم ، ولكن في الأيام الأخيرة ، بحثت في ويب كامل لحل هذا السؤال نفسه. لدي الكعك REST خدمات الويب و iPhone العميل التي ترسل الصور والعنوان والوصف.

لا أعلم ما إذا كانت مقاربي هي الأفضل ، ولكنها سهلة وبسيطة.

التقطت صورة باستخدام UIImagePickerController وأرسلها إلى الخادم NSData باستخدام علامات رأس الطلب لإرسال بيانات الصورة.

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

من جانب الخادم ، أتلقى الصورة باستخدام الرمز:

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

}

لا أعرف ما إذا كنت أواجه مشكلات في المستقبل ، لكني الآن أعمل بشكل جيد في بيئة الإنتاج.

ربما سيكون هذا سؤالًا غبيًا ولكني أواجه واحدة من تلك الليالي. في تطبيق أقوم بتطوير RESTful API ونريد من العميل إرسال البيانات باسم JSON. يتطلب جزء من هذا التطبيق من العميل تحميل ملف (عادة صورة) وكذلك معلومات حول الصورة.

أواجه صعوبة في تعقب كيفية حدوث ذلك في طلب واحد. هل من الممكن أن Base64 بيانات الملف إلى سلسلة JSON؟ هل سأحتاج إلى إجراء وظيفتين على الخادم؟ هل يجب ألا أستخدم JSON لهذا؟

كملاحظة جانبية ، نحن نستخدم Grails على الواجهة الخلفية ويتم الوصول إلى هذه الخدمات من قبل عملاء المحمول الأصلي (iPhone ، Android ، الخ) ، إذا كان أي من ذلك يحدث فارقاً.


إذا كنت تقوم بتطوير خادم الراحة يمكنك القيام بذلك

  1. اجعل العميل يعرض الملف عبر HTTP
  2. يمكن للعميل بعد ذلك إرسال عنوان URL مع بيانات json مثل ملف صورة {"file_url":"http://cockwombles.com/blah.jpg"}
  3. يمكن للخادم بعد ذلك تنزيل الملف.

طرحت سؤالا مماثلا هنا:

كيف أقوم بتحميل ملف يحتوي على بيانات وصفية باستخدام خدمة REST على الويب؟

لديك في الأساس ثلاثة خيارات:

  1. ترميز Base64 الملف ، على حساب زيادة حجم البيانات بنحو 33 ٪.
  2. أرسل الملف أولاً في POST multipart/form-data ، ثم قم بإرجاع معرف إلى العميل. ثم يرسل العميل البيانات التعريفية بالمعرف ، ويقوم الخادم بإعادة إقران الملف والبيانات التعريفية.
  3. أرسل البيانات التعريفية أولاً ، ثم قم بإرجاع معرف إلى العميل. ثم يرسل العميل الملف بالمعرف ، ويقوم الخادم بإعادة إقران الملف والبيانات التعريفية.

في ما يلي واجهة برمجة التطبيقات الخاصة بي (أنا استخدم مثالاً) - كما ترى ، فأنا لا أستخدم أي file_id (ملف التعريف المودع في الخادم) في API:

1. إنشاء كائن "الصورة" على الخادم:

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

2. ملف التحميل (لاحظ أن "الملف" هو في صيغة فريدة لأنه واحد فقط لكل صورة):

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

ثم على سبيل المثال:

3.Read قائمة الصور

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

4.Read بعض تفاصيل الصورة

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

5.Read ملف الصورة

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

وبالتالي فإن الاستنتاج هو أن ، أولا قمت بإنشاء كائن (صورة) من قبل POST ، ثم قمت بإرسال طلب secod مع الملف (مرة أخرى POST).


وأنا أعلم أن هذا الموضوع قديم جدا ، ومع ذلك ، أنا في عداد المفقودين هنا خيار واحد. إذا كان لديك بيانات وصفية (بأي تنسيق) ترغب في إرسالها مع البيانات المراد تحميلها ، فيمكنك إجراء طلب واحد multipart/related طلب multipart/related .

يقصد نوع الوسائط المتعددة / الوسائط ذات الصلة بالكائنات المركبة التي تتكون من عدة أجزاء مترابطة في الجسم.

يمكنك التحقق من مواصفات RFC 2387 للحصول على تفاصيل أكثر تفصيلاً.

أساسا كل جزء من هذا الطلب يمكن أن يكون المحتوى مع نوع مختلف وجميع الأجزاء ترتبط بطريقة أو بأخرى (على سبيل المثال صورة والبيانات الوصفية). يتم تحديد الأجزاء من خلال سلسلة حدود ، ويتبع سلسلة الحدود النهائية بوصلتين.

مثال:

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

يرجى التأكد من أن لديك متابعة الاستيراد. Ofcourse الواردات القياسية الأخرى

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
    }

@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