Tengo un servicio web REST que actualmente expone esta URL:
http: // servidor / datos / medios
donde los usuarios pueden POST
el siguiente JSON:
{
"Name": "Test",
"Latitude": 12.59817,
"Longitude": 52.12873
}
para crear nuevos metadatos de medios.
Ahora necesito la capacidad de cargar un archivo al mismo tiempo que los metadatos de los medios. ¿Cuál es la mejor manera de hacer esto? Podría introducir una nueva propiedad llamada file
y base64 codificar el archivo, pero me preguntaba si había una mejor manera.
También se usa multipart/form-data
como lo que enviaría un formulario HTML, pero estoy usando un servicio web REST y quiero seguir usando JSON si es posible.
web-services
json
rest
file-upload
Daniel T.
fuente
fuente
Respuestas:
Estoy de acuerdo con Greg en que un enfoque de dos fases es una solución razonable, sin embargo, lo haría al revés. Yo lo haría:
Para crear la entrada de metadatos y devolver una respuesta como:
El cliente puede usar este ContentUrl y hacer un PUT con los datos del archivo.
Lo bueno de este enfoque es que cuando su servidor comienza a ser pesado con inmensos volúmenes de datos, la url que devuelve puede apuntar a otro servidor con más espacio / capacidad. O podría implementar algún tipo de enfoque round robin si el ancho de banda es un problema.
fuente
El hecho de que no esté envolviendo todo el cuerpo de la solicitud en JSON, no significa que no sea RESTful usar
multipart/form-data
para publicar tanto el JSON como los archivos en una sola solicitud:en el lado del servidor (usando Python para pseudocódigo):
para cargar múltiples archivos, es posible usar "campos de formulario" separados para cada uno:
... en cuyo caso el código del servidor tendrá
request.args['file1'][0]
yrequest.args['file2'][0]
o reutilice el mismo para muchos:
... en cuyo caso
request.args['files']
simplemente será una lista de longitud 2.o pasar múltiples archivos a través de un solo campo:
... en cuyo caso
request.args['files']
será una cadena que contiene todos los archivos, que tendrá que analizar usted mismo, no estoy seguro de cómo hacerlo, pero estoy seguro de que no es difícil, o mejor simplemente use los enfoques anteriores.La diferencia entre
@
y<
es que@
hace que el archivo se adjunte como una carga de archivo, mientras que<
adjunta el contenido del archivo como un campo de texto.PD: Solo porque lo estoy usando
curl
como una forma de generar lasPOST
solicitudes no significa que no se puedan enviar exactamente las mismas solicitudes HTTP desde un lenguaje de programación como Python o usando una herramienta suficientemente capaz.fuente
curl -f 'metadata={"foo": "bar"}'
?Una forma de abordar el problema es hacer que la carga sea un proceso de dos fases. Primero, cargaría el archivo usando una POST, donde el servidor devuelve algún identificador al cliente (un identificador podría ser el SHA1 del contenido del archivo). Luego, una segunda solicitud asocia los metadatos con los datos del archivo:
La inclusión de la base de datos del archivo 64 codificada en la solicitud JSON aumentará el tamaño de los datos transferidos en un 33%. Esto puede o no ser importante dependiendo del tamaño general del archivo.
Otro enfoque podría ser usar una POST de los datos del archivo sin formato, pero incluir cualquier metadato en el encabezado de la solicitud HTTP. Sin embargo, esto queda un poco fuera de las operaciones REST básicas y puede ser más incómodo para algunas bibliotecas de cliente HTTP.
fuente
Me doy cuenta de que esta es una pregunta muy antigua, pero espero que esto ayude a alguien más cuando llegué a esta publicación buscando lo mismo. Tuve un problema similar, solo que mis metadatos eran Guid e int. Sin embargo, la solución es la misma. Simplemente puede hacer que los metadatos necesarios formen parte de la URL.
Método de aceptación POST en su clase "Controlador":
Luego, en lo que sea que esté registrando rutas, WebApiConfig.Register (HttpConfiguration config) para mí en este caso.
fuente
Si su archivo y sus metadatos crean un recurso, está bien cargarlos en una sola solicitud. La solicitud de muestra sería:
fuente
No entiendo por qué, en el transcurso de ocho años, nadie ha publicado la respuesta fácil. En lugar de codificar el archivo como base64, codifique el json como una cadena. Luego simplemente decodifique el json en el lado del servidor.
En Javascript:
Publíquelo usando Content-Type: multipart / form-data
En el lado del servidor, recupere el archivo normalmente y recupere el json como una cadena. Convierta la cadena en un objeto, que generalmente es una línea de código, sin importar el lenguaje de programación que use.
(Sí, funciona muy bien. Hacerlo en una de mis aplicaciones).
fuente