파일 및 관련 데이터를 JSON처럼 RESTful 웹 서비스에 게시하는 것이 바람직하다.



Answers

multipart/form-data 콘텐츠 유형을 사용하여 하나의 요청으로 파일과 데이터를 보낼 수 있습니다.

많은 응용 프로그램에서 사용자가 양식을 제공받을 수 있습니다. 사용자는 입력 된 정보, 사용자 입력에 의해 생성 된 정보 또는 사용자가 선택한 파일에 포함 된 정보를 포함하여 양식을 채 웁니다. 양식이 채워지면 양식의 데이터가 사용자로부터 수신 응용 프로그램으로 전송됩니다.

MultiPart / Form-Data의 정의는 해당 응용 프로그램 중 하나에서 파생됩니다.

http://www.faqs.org/rfcs/rfc2388.html :

"multipart / form-data"는 일련의 부분을 포함합니다. 각 부분은 폐기 유형이 "양식 데이터"인 내용 처분 헤더 [RFC 2183]를 포함해야하며 처분에는 "이름"의 (추가) 매개 변수가 포함됩니다. 여기서 매개 변수의 값은 원래 값입니다 양식의 필드 이름. 예를 들어, 파트에 머리글이 포함될 수 있습니다.

내용 - 처분 : 양식 데이터; 이름 = "사용자"

"사용자"필드의 항목에 해당하는 값으로 대체하십시오.

경계 사이의 각 섹션 내에 파일 정보 또는 필드 정보를 포함 할 수 있습니다. 나는 사용자가 데이터와 폼을 모두 제출해야하는 RESTful 서비스를 성공적으로 구현했으며, multipart / form-data는 완벽하게 작동했다. 서비스는 Java / Spring을 사용하여 작성되었으며 클라이언트는 C #을 사용 했으므로 불행하게도 서비스 설정 방법에 관한 Grails 예제가 없습니다. 이 경우 각 "form-data"섹션에서 매개 변수의 이름과 그 값을 지정할 수있는 곳을 제공하므로 JSON을 사용할 필요가 없습니다.

multipart / form-data 사용에 대한 좋은 점은 HTTP 정의 헤더를 사용한다는 것입니다. 따라서 기존 HTTP 도구를 사용하여 서비스를 만드는 REST 철학을 고수하고 있습니다.

Question

이것은 아마 어리석은 질문 일 것입니다.하지만 저는 그날 밤을 보내고 있습니다. 응용 프로그램에서 RESTful API를 개발 중이며 클라이언트가 JSON으로 데이터를 보내길 원합니다. 이 응용 프로그램의 일부는 클라이언트가 파일 (일반적으로 이미지)과 이미지에 대한 정보를 업로드해야합니다.

나는 이것이 단일 요청에서 어떻게 발생 하는지를 추적하는 데 어려움을 겪고있다. Base64에 파일 데이터를 JSON 문자열에 넣을 수 있습니까? 서버에 2 개의 게시물을 수행해야합니까? JSON을 사용하지 않아야합니까?

사이드 노트에서 우리는 백엔드에서 Grails를 사용하고 있으며 이러한 서비스가 네이티브 모바일 클라이언트 (iPhone, Android 등)에 의해 액세스되는 경우 차이가 있습니다.




여기에 내 접근 API를 (나는 예제를 사용) - 당신이 볼 수 있듯이, API에서 file_id (서버에 업로드 된 파일 식별자)를 사용하지 않습니다.

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. 사진 목록 읽기

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

4. 일부 사진 세부 정보 읽기

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

5. 사진 파일 읽기

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

결론적으로 먼저 POST로 객체 (사진)를 만든 다음 secod 요청을 파일 (다시 POST)로 보냅니다.




나머지 서버를 개발하고 있다면 이것을 할 수 있습니다.

  1. 클라이언트가 HTTP를 통해 파일을 노출하게하십시오.
  2. 클라이언트는 json 데이터 (예 : 이미지 파일 {"file_url":"http://cockwombles.com/blah.jpg"} 와 함께 URL을 보낼 수 있습니다 {"file_url":"http://cockwombles.com/blah.jpg"}
  3. 그런 다음 서버는 파일을 다운로드 할 수 있습니다.



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



나는이 질문이 오래되었다는 것을 알고있다. 그러나 마지막 날에 나는이 동일한 질문을 해결하기 위해 전체 웹을 조사했다. 나는 사진, 제목 및 설명을 보내는 grails REST webservices 및 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")

}

나는 미래에 문제가 있을지 모르지만 현재 생산 환경에서 잘 작동하고 있습니다.




Related