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



5 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

file upload restful api

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

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

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




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

}

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




단 누락 된 예제는 ANDROID 예제 이므로 추가하겠습니다. 이 기술은 Activity 클래스 내부에서 선언해야하는 사용자 정의 AsyncTask를 사용합니다.

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 (e.g. 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);
    }

}

따라서 파일을 업로드하려면 다음을 호출하십시오.

new UploadFile().execute();



백엔드 서버에 문자열을 보내고 싶었습니다. 내가 multipart 함께 json 사용하지 않았다, 나는 요청 매개 변수를 사용했습니다.

@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은 다음과 같이 보입니다.

http://localhost:8080/file/upload?uuid=46f073d0&type=PASSPORT

파일 업로드와 함께 두 개의 매개 변수 (uuid 및 type)를 전달합니다. 이것이 json 데이터를 보낼 복잡한 사람이없는 사람에게 도움이되기를 바랍니다.




다음과 같은 수입품을 가지고 있는지 확인하십시오. 물론 기타 표준 수입품

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
    }


Related