Enviar ficheros al servidor que residen en la máquina cliente mediante http POST

Siguiendo con el último artículo, supongamos que lo que queremos es enviar al servidor una o varias imágenes que están en la máquina cliente. Este es un tema muy espinoso y lo más recomendable es instalar un servidor web en la máquina cliente y hacer que el servidor vaya a buscar esos ficheros.

También es cierto que por tema de "atomicidad" queda más bonito enviar imágenes y datos en un solo POST que sólo puede o tener éxito o fallar.

Si en concreto usamos chrome en el cliente, podemos hacer un sencillo "work arround" instalando una extensión de chrome que pida la lectura de unos ficheros en concreto y dándole permisos. Esto tiene la ventaja de que hacemos un solo POST con toda la información necesaria.

Para acceder a los ficheros en el cliente, primero creamos el manifiesto de la extensión de chrome con la lista de ficheros a los que queremos acceder, que deben estar todos en el mismo directorio. El manifiesto también lo guardamos en ese directorio.

manifest.json

{
"name": "File holder",
"manifest_version": 2,
"version": "1.0",
"web_accessible_resources": ["imagen1.jpg", "imagen2.jpg", "imagen3.jpg"]
}

Ahora, instalamos la extensión: Vamos a chrome->extensions, activamos developer mode y hacemos Load unpacked extension. A partir de este momento, podemos acceder las imágenes locales desde el navegador con
chrome-extension://[app-id]/[imagen]

donde [app-id] es el id de aplicación que nos sale cuando instalamos  la extensión. Ya podemos acceder a los ficheros locales con el protocolo chrome-extension, por ejemplo con

chrome-extension://debeanplnpndkfnlbalbmkikofkghfmk/imagen1.jpg

Podemos enviar la imagen al servidor mediante un POST, así:

    $("#bt_envia").on("click", function (e) {

var x = new XMLHttpRequest();
x.onload = function() {
// Create a form
var fd = new FormData();
fd.append("upfile", x.response);
fd.append("csrfmiddlewaretoken", "{{ csrf_token }}");

// Upload to your server
var y = new XMLHttpRequest();
y.onload = function() {
alert('File uploaded!');
};
y.open('POST', '/gestion/prova/');
y.send(fd);
};
x.responseType = 'blob';
x.open('GET', 'chrome-extension://debeanplnpndkfnlbalbmkikofkghfmk/foto.jpg');
x.send();

});


Fuente: varios en stackoverflow y
http://stackoverflow.com/questions/10611796/is-there-any-way-to-load-a-local-js-file-dynamically

Django hacer POST desde javascript con contenido binario

Si queremos hacer un POST con contenido binario como una imagen desde el navegador contra Django, tenemos que tener en cuenta que la llamada a ajax  codifica el stream en UTF-8.

Para desactivar este funcionamiento y hacer el envío "raw" tenemos que poner el responseType como 'blob', de esta forma:

    $("#bt_envia").on("click", function (e) {

var x = new XMLHttpRequest();
x.onload = function() {
// Create a form
var fd = new FormData();
fd.append("upfile", x.response); // x.response is a Blob object
fd.append("csrfmiddlewaretoken", "{{ csrf_token }}");

// Upload to your server
var y = new XMLHttpRequest();
y.onload = function() {
alert('Fichero subido!!');
};
y.open('POST', '/gestion/prova/');
y.send(fd);
};
x.responseType = 'blob';
x.open('GET', 'http://planetary.s3.amazonaws.com/assets/images/spacecraft/2013/20131108_2013-3896_f537.jpg', true);
x.send();

En la parte del servidor, los FILES nos vendrán directamente en el formato nativo, así que sólo tenemos que tratarlos directamente, por ejemplo grabando una imagen en un fichero.

def prova(request):
#print str(request.body)
# veure https://docs.djangoproject.com/en/dev/topics/http/file-uploads/
print "Els files son ", str(request.FILES)
f = request.FILES['upfile']
with open('c:/prova.jpg', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)

return HttpResponse('Mu guay')


Fuente: varios en stackoverflow

Naves espaciales: Masa de la nave y masa de los instrumentos

Es sabido que la física de un lanzamiento está impuesta, entre otras cosas, por la ecuación del cohete, por el tipo de trayectoria que se escoja para llegar al destino y por las características de la misión. Esto provoca situaciones como la de la MAVEN (extraido de planetary society), cito:

"The launch mass is 2,454 kilograms, of which 1,645 kg is fuel and only 809 is spacecraft. Of that, the instrument package weighs in at 65 kilograms, and there's an additional 6.5 kilograms devoted to the Electra instrument that allows relay from rovers and landers to Earth."

O sea, que para poner 65 Kg de instrumentos en Marte hay que usar una nave de 2.454 Kg. Es decir, que la verdadera "carga útil" de la nave es el 65/2454 = 2,6% del total. También es cierto que lleva mucho combustible por el tipo de misión.

De todas formas, para el lanzamiento se usará un Atlas V-401 cuya pinta es esta:


Pero es que este bichito tiene una masa de 546.700 Kg. por lo que realmente los 65Kg en Marte implican un 0.000118%, es decir, un uno por diez mil del lanzamiento. Curioso.

Imagen: NASA

Uso del atributo data en html5

Html5 nos permite pasar datos arbitrarios en las etiquetas y que estas sigan siendo válidas sin tener que crear una dtd.

El único requerimiento es que el nombre del atributo de la etiqueta debe empezar por data-.

Así, esto es válido en html5:





E incluso podemos pasar datos en formato json:





Realmente útil y además valida.

Hey!, muy guay! ¿Pero qué hay acerca del tratamiento de estos atributos en la hoja de estilos?. Pues también mola porque podemos tratar los data- como cualquier otro atributo.

Vamos a saludar el santo a todos clientes que se llamen Pepe con CSS:


Rodrígez Pérez, José


Y la hoja de estilo:
div[data-nombre="Pepe"] { 
background-color: red;
}
div[data-nombre="Pepe"]:after {
content: attr(data-saludo);
}




Para saber más:

htmldoctor
tutsplus