An Interest In:
Web News this Week
- March 28, 2024
- March 27, 2024
- March 26, 2024
- March 25, 2024
- March 24, 2024
- March 23, 2024
- March 22, 2024
Cargar archivos a Google Drive con Phoenix LiveView
Phoenix LiveView tiene una gran abstraccin a la hora de realizar subida de archivos. Nos facilita bastante la vida tanto desde el lado del cliente (interfaz de usuario) como desde el lado del servidor (nuestro servidor local o incluso a servicios de terceros como servicios en la nube).
Este post est enfocado en ayudarte con la subida de archivos al servicio de Google Drive, ya que muchas veces los servicios de Google son difciles de entender y lleva tiempo el poder descubrir la manera de hacer una integracin exitosa, como lo fue mi caso. Es por esto que quisiera compartir con la comunidad la manera de como logr hacerlo despus de mucho tiempo de bsqueda y ensayos.
Comencemos...
Esta gua no pretende mostrar el detalle de cmo funciona el proceso de subida de archivos en Phoenix LiveView. Mejor, pretende mostrar la integracin de Google Drive con lo que ya las guas External Uploads de Phoenix LiveView y Phoenix LiveView Uploads Deep Dive por Chris McCord ya muestran de una manera super clara y fcil de entender.
Para conocer el detalle de cmo funciona el proceso de subida de archivos en Phoenix LiveView puedes mirar las guas anteriormente mencionadas.
Requerimientos previos
Lo primero que debemos tener en cuenta es que inicialmente debemos habilitar el acceso a la API de Google Drive, esto lo puedes lograr visitando la documentacin de Google Drive API.
Asegrate de crear una Cuenta de Servicio en Google Cloud y por ltimo tener el archivo .json con las credenciales de tu Cuenta de Servicio de Google Cloud. Este archivo debe contener algo parecido a esto:
{ "type": "service_account", "project_id": "<your google cloud project>", "private_key_id": "<your private key id>", "private_key": "<your private key>", "client_email": "<your client email>", "client_id": "<your client id>", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "<your client x509 cert url>"}
Configuracin de dependencias
Para poder realizar la autenticacin con los servicios de Google usaremos la librera Goth (Google + Auth).
Aadimos Goth a nuestras dependencias en el archivo mix.exs
defp deps do [ ... {:goth, "~> 1.2.0"} ] end
Corremos la siguiente lnea en la consola para descargar nuestras dependencias:
$ mix deps.get
Y por ltimo debemos exponer una variable de ambiente llamada GOOGLE_APPLICATION_CREDENTIALS con la cual Goth tendra lo necesario para obtener un access token:
$ export GOOGLE_APPLICATION_CREDENTIALS=<your_service_account_file>.json
Donde <your_service_account_file> es el path al archivo .json que contiene las credenciales de tu Cuenta de Servicio de Google Cloud.
(Este archivo es sencible, no lo deberas aadir en tu repositorio de cdigo)
Vamos al cdigo...
Del lado de nuestra LiveView
En nuestro archivo de LiveView debemos habilitar la carga de archivos. Para ello en la funcin mount, modificamos:
def mount(socket) do {:ok, allow_upload( socket, :photos, accept: ~w(.png .jpeg .jpg), max_entries: 2, external: &presign_entry/2 )} end
La propiedad accept habilita la subida de archivos aceptando nicamente formatos .png, .jpeg o .jpg, en este caso. La propiedad max_entries permite la subida de mximo dos (2) archivos.
La propiedad external debe ser una funcin callback con dos parmetros. Esta funcin ser en realidad la encargada de llamar a la funcin que sube los arhivos a Google Drive, pasndole los datos necesarios para realizar la subida. Cuando usamos external es porque la funcin que se encargar de subir los archivos ser una funcin de JavaScript (en el lado del cliente). Lo haremos con JavaScript ya que ms adelante queremos saber el progreso de subida de cada uno de los archivos, saber si hay un error en este proceso de subida o si hay un error en la validacin de los archivos. Todo esto usando XMLHttpRequest de JavaScript.
Aadimos nuestra funcin presign_entry en nuestro archivo de LiveView:
@google_drive_url "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart" @google_drive_scope "https://www.googleapis.com/auth/drive.file" defp presign_entry(entry, socket) do {:ok, %{token: token}} = Goth.Token.for_scope(@google_drive_scope) fields = %{ name: "#{entry.uuid}.#{ext(entry)}", content_type: entry.client_type, token: token } {:ok, %{uploader: "GoogleDriveMultipart", url: @google_drive_url, fields: fields}, socket} end defp ext(entry) do [ext | _] = MIME.extensions(entry.client_type) ext end
Aadimos la funcin callback handle_event para manejar el evento de cancelacin de subida de alguno de los archivos:
def handle_event("cancel-entry", %{"ref" => ref}, socket) do {:noreply, cancel_upload(socket, :photos, ref)}end
Aadimos los componentes Phoenix HTML para la subida de los archivos:
... <%= live_file_input @uploads.photos %> <%= for {_ref, msg} <- @uploads.photos.errors do %> <p class="alert alert-danger"> <%= Phoenix.Naming.humanize(msg) %> </p> <% end %> <%= for entry <- @uploads.photos.entries do %> <%= live_img_preview(entry) %> <progress max="100" value="<%= entry.progress %>" /> <a href="#" phx-click="cancel-entry" phx-value-ref="<%= entry.ref %>" > Cancel </a> <% end %>
Del lado de JavaScript
En el archivo app.js habilitamos la carga externa de archivos aadiendo lo siguiente:
import { uploadPhotosToGoogleDrive } from "./uploaders/google-drive"const Uploaders = { GoogleDriveMultipart: uploadPhotosToGoogleDrive}let liveSocket = new LiveSocket("/live", Socket, { uploaders: Uploaders, params: { _csrf_token: csrfToken }})
En la carpeta uploaders creamos el archivo google-drive.js aadiendo lo siguiente:
const createRequestPayload = (fields, photo) => { const boundary = 'uploading photos' const multipartRequestHeaders = [ ['Content-Type', `multipart/related; boundary="${boundary}"`], ['Authorization', `Bearer ${fields.token}`] ] const delimiter = "\r
--" + boundary + "\r
" const close_delim = "\r
--" + boundary + "--" const contentType = fields.content_type const metadata = { 'name': fields.name, 'mimeType': contentType, 'parents': [fields.parent] } const base64Data = btoa(photo) const multipartRequestBody = delimiter + 'Content-Type: application/json; charset=UTF-8\r
\r
' + JSON.stringify(metadata) + delimiter + 'Content-Type: ' + contentType + '\r
' + 'Content-Transfer-Encoding: base64\r
' + '\r
' + base64Data + close_delim return { multipartRequestHeaders, multipartRequestBody }}export const uploadPhotosToGoogleDrive = (entries, onViewError) => { entries.forEach(entry => { const { file, meta: { url, fields } } = entry const reader = new FileReader() reader.readAsBinaryString(file) reader.onload = () => { const { multipartRequestHeaders, multipartRequestBody } = createRequestPayload(fields, reader.result) const xhr = new XMLHttpRequest() onViewError(() => xhr.abort()) xhr.onprogress = event => { if (event.lengthComputable) { const percent = Math.round((event.loaded / event.total) * 100) entry.progress(percent) } } xhr.open("POST", url, true) multipartRequestHeaders.map(([key, value]) => { xhr.setRequestHeader(key, value) }) xhr.send(multipartRequestBody) xhr.onload = () => { if (xhr.status !== 200) { return entry.error() } } xhr.onerror = () => entry.error() } })}
Eso es todo! Probemos...
Al probar la carga de archivos podremos ver cmo el progreso de subida muestra la barra al 100% completa.
Y por ltimo, en los DevTools podremos ver una respuesta exitosa obtenida por Google Drive API. De la cual podremos saber el tipo de subida, el ID del archivo dentro de Google Drive, el nombre y el formato de este.
Y listo, tienes tu archivo en Google Drive!
Para ver la implementacin completa puedes visitar el repo:
santiagocardo80 / car-workshop
Car Workshop Managment Web App
CarWorkshop
To start your Phoenix server:
- Install dependencies with
mix deps.get
- Create and migrate your database with
mix ecto.setup
- Install Node.js dependencies with
npm install
inside theassets
directory - Start Phoenix endpoint with
mix phx.server
Now you can visit localhost:4000
from your browser.
Ready to run in production? Please check our deployment guides.
Learn more
- Official website: https://www.phoenixframework.org/
- Guides: https://hexdocs.pm/phoenix/overview.html
- Docs: https://hexdocs.pm/phoenix
- Forum: https://elixirforum.com/c/phoenix-forum
- Source: https://github.com/phoenixframework/phoenix
Original Link: https://dev.to/santiagocardo/cargar-archivos-a-google-drive-con-phoenix-liveview-5581
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To