REST API - обработка файлов (т. е. изображений) - рекомендации



мы разрабатываем сервер с REST API, который принимает и отвечает с помощью JSON. Проблема в том, что вам нужно загружать изображения с клиента на сервер.



обратите внимание также, что я говорю о прецеденте, где сущность (пользователь) может иметь файлы (carPhoto, licensePhoto), а также иметь другие свойства (имя, адрес электронной почты...), но когда вы создаете нового пользователя, вы не отправляете эти изображения, они добавляются после процесса регистрации.





решения, о которых я знаю, но каждый из них есть некоторые недостатки



1. Используйте multipart / form-data вместо JSON



хороший : запросы POST и PUT максимально спокойны, они могут содержать текстовые входы вместе с файлом.



минусы : это больше не JSON, который намного проще тестировать, отлаживать и т. д. сравните с multipart / form-data



2. Разрешить обновление отдельных файлов



POST запрос на создание нового пользователь не позволяет добавлять изображения (что нормально в нашем случае использования, как я сказал в начале), загрузка изображений выполняется путем запроса PUT в виде составных / форм-данных, например /users/4 / carPhoto



хороший: все (кроме самой загрузки файла) остается в JSON, его легко тестировать и отлаживать (вы можете регистрировать полные запросы JSON, не боясь их длины)



минусы : это не интуитивно, вы не можете разместить или поставить все переменные сущность сразу и также Этот адрес /users/4/carPhoto можно рассматривать больше как коллекцию (стандартный вариант использования для REST API выглядит так /users/4/shipments). Обычно вы не можете (и не хотите) получить/поместить каждую переменную сущности, например users/4/name . Вы можете получить имя с GET и изменить его с помощью PUT at users/4. Если есть что-то после идентификатора, это обычно другая коллекция, например users/4/reviews



3. Используют Base64



отправить его как JSON, но кодировать файлы с помощью В base64.



хороший: то же самое, что и первое решение, это как можно более спокойное обслуживание.



минусы : опять же, тестирование и отладка намного хуже (тело может иметь мегабайты данных), есть увеличение размера, а также времени обработки в обоих - клиент и сервер





Я бы очень хотел использовать решение № 2, но у него есть свои минусы... Любой может дать мне лучшее представление о том, " что лучше" решение?



моя цель состоит в том, чтобы иметь RESTful услуги с максимально возможным количеством стандартов, в то время как я хочу, чтобы это было как можно проще.

3410   4  

4 ответов:

есть несколько решений, чтобы сделать:

  1. о путь к ресурсу:

    • моделируйте изображение как ресурс самостоятельно:

      • вложенный в пользователя (/user/: id / image): связь между Пользователем и изображением выполняется неявно

      • в корневом пути (/image):

        • клиент несет ответственность за установление связи между изображением и пользователем, или;

        • если контекст безопасности предоставляется с запросом POST, используемым для создания образа, сервер может неявно установить связь между аутентифицированным пользователем и образом.

    • вставить изображение как часть пользователя

  2. второе решение-это как представляем ресурс изображения:

    • как база 64 кодируется JSON полезная нагрузка
    • как составная полезная нагрузка

Это было бы мое решение трек:

  • Я обычно предпочитаю дизайн по сравнению с производительностью, если для этого нет веских оснований. Это делает систему более ремонтопригодной и может быть более легко понято интеграторами.
  • Итак, моя первая мысль-пойти на Base64 представление ресурса изображения, потому что он позволяет сохранить все JSON. Если вы выбрали эту опцию, вы можете моделировать путь к ресурсу по своему усмотрению.
    • если отношение между Пользователем и изображением составляет 1 к 1, я бы предпочел моделировать изображение как атрибут, особенно если оба набора данных обновляются одновременно. В любом другом случае вы можете свободно выбрать модель изображения либо как атрибут, обновляя его с помощью PUT или PATCH, либо как отдельный ресурс.
  • если вы выберете составную полезную нагрузку, я буду вынужден моделировать изображение как ресурс самостоятельно, так что на другие ресурсы, в нашем случае на пользовательский ресурс, не влияет решение об использовании двоичного представления для изображения.

тогда возникает вопрос:есть ли влияние на производительность при выборе base64 против multipart?. Мы могли бы подумать, что обмен данными в составном формате должен быть более эффективным. Но в этой статье показывает, как мало оба представления отличаются по размеру.

мой выбор Base64:

  • последовательное проектное решение
  • незначительное влияние на производительность
  • поскольку браузеры понимают URI данных (закодированные изображения base64), нет необходимости преобразовывать их, если клиент является браузером
  • Я не буду голосовать за то, чтобы иметь его в качестве атрибута или автономного ресурса, это зависит от вашего проблемная область (которую я не знаю) и ваши личные предпочтения.

ОП (я отвечаю на этот вопрос через два года, сообщение, сделанное Даниэлем Сереседо, было неплохо в то время, но веб-сервисы развиваются очень быстро)

после трех лет полной разработки программного обеспечения (С акцентом на архитектуру программного обеспечения, управления проектами и архитектуры, конструирование), я однозначно выберу второй путь (но с одной общей конечной точки) как лучший.

Если у вас есть специальные точки для изображения, это дает вам гораздо больше власти над процессом обработки изображений.

У нас есть тот же REST API (узел.js) для обоих - мобильных приложений (iOS/android) и frontend (с помощью React). Это 2017 год, поэтому вы не хотите хранить изображения локально, вы хотите загрузить их в облачное хранилище (google cloud, s3, cloudinary,...), поэтому вы хотите некоторую общую обработку над ними.

наш типичный поток заключается в том, что как только вы выбираете изображение, оно начинает загружаться на фоне (обычно POST on / images endpoint), возвращая вам идентификатор после загрузки. Это действительно удобно, потому что пользователь выбирает изображение, а затем обычно переходит к некоторым другим полям (т. е. адрес, имя,...), поэтому, когда он нажимает кнопку "отправить", изображение обычно уже загружено. Он не ждет и смотрит на экран, говоря: "uploadiing...".

то же самое касается и получения изображений. Особенно благодаря мобильным телефонам и ограниченным мобильным данным, Вы не хотите отправлять оригинальные изображения, вы хотите отправить измененные изображения, поэтому они не принимают так много данных (и чтобы сделать ваши мобильные приложения быстрее, вы часто не хотите изменять их размер вообще, вы хотите, чтобы изображение идеально вписывалось в ваш взгляд). По этой причине, хорошие приложения, используя что-то вроде cloudinary (или у нас есть собственный сервер для изменения размера изображения).

кроме того, если данные не являются частными, то вы отправляете обратно в приложение/интерфейс только URL-адрес, и он загружает его из облачного хранилища напрямую, что является огромной экономией полосы пропускания и времени обработки для ваш сервер. В наших больших приложениях каждый месяц загружается много терабайт, вы не хотите обрабатывать это непосредственно на каждом сервере REST API, который ориентирован на работу с CRUD. Вы хотите обрабатывать это в одном месте (наш Imageserver, который имеет кэширование и т. д.) или пусть облачные сервисы обрабатывают все это.


минусы: единственные "минусы", о которых вы должны думать, это "не назначенные изображения". Пользователь выбирает изображения и продолжает заполнять другие поля, но затем он говорит "нет" и выключите приложение или вкладку, но тем временем вы успешно загрузили изображение. Это означает, что вы загрузили изображение, которое нигде не назначено.

есть несколько способов справиться с этим. Самый простой из них - "мне все равно", что актуально, если это происходит не очень часто или у вас даже есть желание хранить каждое изображение, которое пользователь отправляет вам (по любой причине), и вы не хотите никакого удаления.

другой тоже легко - у вас есть CRON и т. е. каждую неделю, и вы удаляете все неназначенные изображения старше одной недели.

ваше второе решение, вероятно, самое правильное. Вы должны использовать спецификацию HTTP и mimetypes так, как они были предназначены, и загрузить файл через multipart/form-data. Что касается обработки отношений, я бы использовал этот процесс (имея в виду, что я знаю ноль о ваших предположениях или системном дизайне):

  1. POST to /users создать объект пользователя.
  2. POST изображение /images, убедившись, вернуть Location заголовок, где изображение может быть извлекается по спецификации HTTP.
  3. PATCH до /users/carPhoto и присвоить ему идентификатор фотографии, приведенной в Location заголовок шага 2.

там нет простого решения. Каждый способ имеет свои плюсы и минусы . Но канонический способ использует первый вариант:multipart/form-data. Как руководство по рекомендации W3 говорит

тип контента "multipart / form-data" должен использоваться для отправки форм, содержащих файлы, данные, отличные от ASCII, и двоичные данные.

мы не отправляем формы, на самом деле, но неявный принцип по-прежнему применяется. Использование base64 в качестве двоичного представления неверно, потому что вы используете неверный инструмент для достижения своей цели, с другой стороны, второй вариант заставляет ваших клиентов API выполнять больше работы, чтобы использовать ваш сервис API. Вы должны выполнить тяжелую работу на стороне сервера, чтобы предоставить простой в использовании API. Первый вариант нелегко отлаживать, но когда вы это делаете, он, вероятно, никогда не меняется.

используя multipart/form-data вы придерживаетесь философии REST/http. Вы можете просмотреть ответ на аналогичный вопрос здесь.

другой вариант при смешивании альтернатив вы можете использовать multipart/form-data, но вместо того, чтобы отправлять каждое значение отдельно, вы можете отправить значение с именем полезная нагрузка с полезной нагрузкой json внутри него. (Я попробовал этот подход, используя ASP.NET WebAPI 2 и отлично работает).

Comments

    Ничего не найдено.