javascript - example - Cargar un archivo con FormData y multer
dropzone js ejemplo (1)
multer
cargar un archivo en un servidor Nodo utilizando el módulo multer
seleccionando el archivo usando el cuadro de diálogo de entrada y luego enviando el formulario, pero ahora necesitaría, en lugar de enviar el formulario, crear un objeto FormData
. y envíe el archivo usando XMLHttpRequest
, pero no está funcionando, el archivo siempre está undefined
en el lado del servidor (enrutador).
La función que hace la solicitud AJAX es:
function uploadFile(fileToUpload, url) {
var form_data = new FormData();
form_data.append(''track'', fileToUpload, fileToUpload.name);
// This function simply creates an XMLHttpRequest object
// Opens the connection and sends form_data
doJSONRequest("POST", "/tracks/upload", null, form_data, function(d) {
console.log(d);
})
}
Tenga en cuenta que fileToUpload
está definido y que la url
es correcta, ya que se llama al método de enrutador correcto. fileToUpload
es un objeto File
obtenido al soltar un archivo del sistema de archivos a una zona de soltar, y luego al acceder a la propiedad dataTransfer
del evento drop.
doJSONRequest
es una función que crea un objeto XMLHttpRequest
y envía el archivo, etc. (como se explica en los comentarios).
function doJSONRequest(method, url, headers, data, callback){
//all the arguments are mandatory
if(arguments.length != 5) {
throw new Error(''Illegal argument count'');
}
doRequestChecks(method, true, data);
//create an ajax request
var r = new XMLHttpRequest();
//open a connection to the server using method on the url API
r.open(method, url, true);
//set the headers
doRequestSetHeaders(r, method, headers);
//wait for the response from the server
r.onreadystatechange = function () {
//correctly handle the errors based on the HTTP status returned by the called API
if (r.readyState != 4 || (r.status != 200 && r.status != 201 && r.status != 204)){
return;
} else {
if(isJSON(r.responseText))
callback(JSON.parse(r.responseText));
else if (callback !== null)
callback();
}
};
//set the data
var dataToSend = null;
if (!("undefined" == typeof data)
&& !(data === null))
dataToSend = JSON.stringify(data);
//console.log(dataToSend)
//send the request to the server
r.send(dataToSend);
}
Y aquí está doRequestSetHeaders
:
function doRequestSetHeaders(r, method, headers){
//set the default JSON header according to the method parameter
r.setRequestHeader("Accept", "application/json");
if(method === "POST" || method === "PUT"){
r.setRequestHeader("Content-Type", "application/json");
}
//set the additional headers
if (!("undefined" == typeof headers)
&& !(headers === null)){
for(header in headers){
//console.log("Set: " + header + '': ''+ headers[header]);
r.setRequestHeader(header, headers[header]);
}
}
}
y mi enrutador para cargar archivos es el siguiente
// Code to manage upload of tracks
var multer = require(''multer'');
var uploadFolder = path.resolve(__dirname, "../../public/tracks_folder");
function validTrackFormat(trackMimeType) {
// we could possibly accept other mimetypes...
var mimetypes = ["audio/mp3"];
return mimetypes.indexOf(trackMimeType) > -1;
}
function trackFileFilter(req, file, cb) {
cb(null, validTrackFormat(file.mimetype));
}
var trackStorage = multer.diskStorage({
// used to determine within which folder the uploaded files should be stored.
destination: function(req, file, callback) {
callback(null, uploadFolder);
},
filename: function(req, file, callback) {
// req.body.name should contain the name of track
callback(null, file.originalname);
}
});
var upload = multer({
storage: trackStorage,
fileFilter: trackFileFilter
});
router.post(''/upload'', upload.single("track"), function(req, res) {
console.log("Uploaded file: ", req.file); // Now it gives me undefined using Ajax!
res.redirect("/"); // or /#trackuploader
});
Supongo que multer
no está entendiendo que fileToUpload
es un archivo con track
nombre (¿no es así?), Es decir, el middleware upload.single("track")
no está funcionando / analizando correctamente o nada, o tal vez simplemente no lo hace trabajar con FormData
, en ese caso sería un desastre. ¿Cuáles serían las alternativas al seguir usando multer?
¿Cómo puedo cargar un archivo usando AJAX y multer?
No dude en preguntar si necesita más detalles.
multer usa solicitudes de tipo de contenido multipart/form-data
para cargar archivos. Eliminar este bit de su función doRequestSetHeaders
debería solucionar su problema:
if(method === "POST" || method === "PUT"){
r.setRequestHeader("Content-Type", "application/json");
}
No necesita especificar el content-type
dado que los objetos FormData
ya usan el tipo de codificación correcto. De los documentos :
Los datos transmitidos están en el mismo formato que el método submit () del formulario utilizaría para enviar los datos si el tipo de codificación del formulario se estableciera en multipart / form-data.
Aquí hay un ejemplo de trabajo. Supone que hay una zona de colocación con la drop-zone
colocación id y un botón de carga con una identificación de upload-button
de upload-button
:
var dropArea = document.getElementById("drop-zone");
var uploadBtn = document.getElementById("upload-button");
var files = [];
uploadBtn.disabled = true;
uploadBtn.addEventListener("click", onUploadClick, false);
dropArea.addEventListener("dragenter", prevent, false);
dropArea.addEventListener("dragover", prevent, false);
dropArea.addEventListener("drop", onFilesDropped, false);
//----------------------------------------------------
function prevent(e){
e.stopPropagation();
e.preventDefault();
}
//----------------------------------------------------
function onFilesDropped(e){
prevent(e);
files = e.dataTransfer.files;
if (files.length){
uploadBtn.disabled = false;
}
}
//----------------------------------------------------
function onUploadClick(e){
if (files.length){
sendFile(files[0]);
}
}
//----------------------------------------------------
function sendFile(file){
var formData = new FormData();
var xhr = new XMLHttpRequest();
formData.append("track", file, file.name);
xhr.open("POST", "http://localhost:3000/tracks/upload", true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error(xhr.statusText);
}
}
};
xhr.send(formData);
}
El código del lado del servidor es una aplicación express simple con el código de enrutador exacto que proporcionó.