IT박스

REST API-파일 (예 : 이미지) 처리-우수 사례

itboxs 2020. 7. 10. 08:11
반응형

REST API-파일 (예 : 이미지) 처리-우수 사례


JSON으로 수락하고 응답하는 REST API를 사용하여 서버를 개발 중입니다. 문제는 클라이언트에서 서버로 이미지를 업로드해야하는 경우입니다.

엔티티 (사용자)가 파일 (carPhoto, licensePhoto)을 가질 수 있고 다른 속성 (이름, 이메일 ...)을 가질 수있는 유스 케이스에 대해 이야기하고 있지만 새로운 사용자를 만들 때 이러한 이미지를 보내지 않습니다. 등록 프로세스 후에 추가됩니다.


내가 알고있는 솔루션이지만 각각의 결함이 있습니다.

1. JSON 대신 multipart / form-data를 사용하십시오.

good : POST 및 PUT 요청은 가능한 한 RESTful이며 텍스트 입력을 파일과 함께 포함 할 수 있습니다.

단점 : 더 이상 JSON이 아니므로 multipart / form-data와 비교하여 테스트, 디버그 등이 훨씬 쉽습니다.

2. 별도의 파일 업데이트 허용

새 사용자를 만들기위한 POST 요청은 이미지를 추가 할 수 없으며 (이것은 유스 케이스에서 내가 시작한 말대로 괜찮습니다) PUT 요청에 의해 그림 업로드는 / parts / 4 / carPhoto와 같은 multipart / form-data로 수행됩니다

good : 파일 업로드 자체를 제외한 모든 것이 JSON에 남아 있으며 테스트 및 디버깅이 쉽습니다 (길이를 두려워하지 않고 완전한 JSON 요청을 기록 할 수 있음)

단점 : 직관적이지 않고 엔티티의 모든 변수를 한 번에 POST 또는 PUT 할 수 없으며이 주소 /users/4/carPhoto는 컬렉션으로 간주 될 수 있습니다 (REST API의 표준 사용 사례는 다음과 같습니다 /users/4/shipments). 일반적으로 엔티티의 각 변수를 GET / PUT 할 수 없습니다 (예 : users / 4 / name). GET으로 이름을 얻고 사용자 / 4에서 PUT으로 변경할 수 있습니다. ID 뒤에 무언가가 있으면 일반적으로 users / 4 / reviews와 같은 다른 컬렉션입니다.

3. Base64 사용

JSON으로 보내지 만 Base64로 파일을 인코딩하십시오.

good : 첫 번째 솔루션과 동일하며 가능한 한 RESTful 서비스입니다.

단점 : 다시 한번, 테스트 및 디버깅이 훨씬 나 빠지고 (본문은 메가 바이트의 데이터를 가질 수 있음) 클라이언트 및 서버 모두에서 크기가 증가하고 처리 시간이 증가합니다.


솔루션 번호를 정말로 사용하고 싶습니다. 2, 그러나 그것의 단점이 있습니다. 누구든지 "최고의 솔루션"에 대한 더 나은 통찰력을 줄 수 있습니까?

저의 목표는 가능한 한 많은 표준이 포함 된 RESTful 서비스를 제공하는 동시에 가능한 한 단순하게 유지하고 싶습니다.


OP 여기 (2 년 후에이 질문에 대답하고 있습니다 .Daniel Cerecedo의 게시물은 한 번에 나쁘지 않았지만 웹 서비스는 매우 빠르게 발전하고 있습니다)

3 년간의 풀 타임 소프트웨어 개발 (소프트웨어 아키텍처, 프로젝트 관리 및 마이크로 서비스 아키텍처에 중점을 둔) 이후, 나는 두 번째 방법 (일반적인 엔드 포인트가있는)을 최고의 것으로 선택했습니다.

이미지에 대한 특별한 엔드 포인트가있는 경우 해당 이미지를 처리하는 데 훨씬 더 많은 힘을줍니다.

모바일 앱 (iOS / android)과 프론트 엔드 (React 사용) 모두에 대해 동일한 REST API (Node.js)가 있습니다. 이것은 2017 년이므로 이미지를 로컬로 저장하지 않고 이미지를 일부 클라우드 저장소 (Google 클라우드, s3, cloudinary 등)에 업로드하려고하므로 일반적인 처리가 필요합니다.

일반적인 흐름은 이미지를 선택하자마자 백그라운드에서 업로드를 시작하고 (일반적으로 / images 엔드 포인트에서 POST) 업로드 후 ID를 반환합니다. 사용자가 이미지를 선택한 다음 일반적으로 다른 필드 (예 : 주소, 이름 등)를 진행하기 때문에 "보내기"버튼을 누르면 이미지가 이미 업로드되기 때문에 이는 실제로 사용자에게 친숙합니다. 그는 "업로드 중 ..."이라는 화면을 기다리지 않고 기다립니다.

이미지를 얻는 것도 마찬가지입니다. 특히 휴대 전화와 제한된 모바일 데이터 덕분에 원본 이미지를 보내지 않고 크기가 조정 된 이미지를 보내려고하므로 대역폭을 많이 차지하지 않으며 모바일 앱을 더 빠르게 만들기 위해 종종 원하지 않습니다. 크기를 전혀 조정하지 않으려면 뷰에 완벽하게 맞는 이미지가 필요합니다. 이러한 이유로 좋은 앱은 cloudinary와 같은 것을 사용하고 있습니다 (또는 크기 조정을 위해 자체 이미지 서버가 있습니다).

또한 데이터가 개인 정보가 아닌 경우 URL을 앱 / 프런트 엔드로 다시 전송하여 클라우드 저장소에서 직접 다운로드하므로 서버의 대역폭 및 처리 시간이 크게 절약됩니다. 더 큰 앱에는 매달 다운로드되는 테라 바이트가 많으므로 CRUD 작업에 중점을 둔 각 REST API 서버에서 직접 처리하고 싶지 않습니다. 한 곳에서 (캐싱이있는 Imageserver) 처리하거나 클라우드 서비스가 모든 것을 처리하도록하십시오.


단점 : 당신이 생각해야 할 유일한 "단점"은 "할당되지 않은 이미지"입니다. 사용자는 이미지를 선택하고 다른 필드를 계속 채우고 "nah"라고 말하고 앱 또는 탭을 끄지 만 이미지를 성공적으로 업로드했습니다. 이것은 어느 곳에도 할당되지 않은 이미지를 업로드했음을 의미합니다.

이를 처리하는 몇 가지 방법이 있습니다. 가장 쉬운 방법은 "I do n't care"입니다. 이것은 매우 자주 발생하지 않거나 사용자가 보내는 모든 이미지를 저장하고 싶을 때 (어떤 이유로 든) 원하지 않는 경우 관련있는 것입니다. 삭제.

또 하나는 쉽습니다-매주 CRON을 가지고 있고 일주일보다 오래된 모든 할당되지 않은 이미지를 삭제합니다.


몇 가지 결정을 내릴 수 있습니다 .

  1. 리소스 경로 에 대한 첫 번째 :

    • 이미지를 자체 리소스로 모델링하십시오.

      • 사용자에 중첩 (/ user / : id / image) : 사용자와 이미지 간의 관계가 암시 적으로 만들어 짐

      • 루트 경로 (/ 이미지)에서 :

        • 고객은 이미지와 사용자 간의 관계를 설정해야 할 책임이 있습니다.

        • If a security context is being provided with the POST request used to create an image, the server can implicitly establish a relationship between the authenticated user and the image.

    • Embed the image as part of the user

  2. The second decision is about how to represent the image resource:

    • As Base 64 encoded JSON payload
    • As a multipart payload

This would be my decision track:

  • I usually favor design over performance unless there is a strong case for it. It makes the system more maintainable and can be more easily understood by integrators.
  • So my first thought is to go for a Base64 representation of the image resource because it lets you keep everything JSON. If you chose this option you can model the resource path as you like.
    • If the relationship between user and image is 1 to 1 I'd favor to model the image as an attribute specially if both data sets are updated at the same time. In any other case you can freely choose to model the image either as an attribute, updating the it via PUT or PATCH, or as a separate resource.
  • If you choose multipart payload I'd feel compelled to model the image as a resource on is own, so that other resources, in our case, the user resource, is not impacted by the decision of using a binary representation for the image.

Then comes the question: Is there any performance impact about choosing base64 vs multipart?. We could think that exchanging data in multipart format should be more efficient. But this article shows how little do both representations differ in terms of size.

My choice Base64:

  • Consistent design decision
  • Negligible performance impact
  • As browsers understand data URIs (base64 encoded images), there is no need to transform these if the client is a browser
  • I won't cast a vote on whether to have it as an attribute or standalone resource, it depends on your problem domain (which I don't know) and your personal preference.

Your second solution is probably the most correct. You should use the HTTP spec and mimetypes the way they were intended and upload the file via multipart/form-data. As far as handling the relationships, I'd use this process (keeping in mind I know zero about your assumptions or system design):

  1. POST to /users to create the user entity.
  2. POST the image to /images, making sure to return a Location header to where the image can be retrieved per the HTTP spec.
  3. PATCH to /users/carPhoto and assign it the ID of the photo given in the Location header of step 2.

There's no easy solution. Each way has their pros and cons . But the canonical way is using the first option: multipart/form-data. As W3 recommendation guide says

The content type "multipart/form-data" should be used for submitting forms that contain files, non-ASCII data, and binary data.

We aren't sending forms,really, but the implicit principle still applies. Using base64 as a binary representation, is incorrect because you're using the incorrect tool for accomplish your goal, in other hand, the second option forces your API clients to do more job in order to consume your API service. You should do the hard work in the server side in order to supply an easy-to-consume API. The first option is not easy to debug, but when you do it, it probably never changes.

Using multipart/form-data you're sticked with the REST/http philosophy. You can view an answer to similar question here.

Another option if mixing the alternatives, you can use multipart/form-data but instead of send every value separate, you can send a value named payload with the json payload inside it. (I tried this approach using ASP.NET WebAPI 2 and works fine).

참고URL : https://stackoverflow.com/questions/33279153/rest-api-file-ie-images-processing-best-practices

반응형