I am trying to upload a file to the server with vuejs, actually i don't want the form to treat the file and upload it, i prevent the submit and treat some logic by myself, so at the begin i want to do something simple just check if it is a pdf and if everything is ok it should point to /upload in the localhost defined for NodeJS server
<template>
<div id="app">
<form>
<h2>Select a file</h2>
<input id="inputVal" type="file" #change="onFileChange">
<button #click.prevent="sendFile()">Send</button>
</form>
</div>
</template>
<!-- Javascript -->
<script>
export default {
name: 'app',
data() {
return {
file: ''
}
},
methods: {
onFileChange(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length) {
return;
}
var ext = files[0].name.split('.').pop();
if(ext === 'pdf') {
this.createFile(files[0]);
}
else {
this.file = '';
this.clearFileInput(document.getElementById('inputVal'));
}
},
createFile(file) {
this.file = file;
},
clearFileInput(ctrl) {
try {
ctrl.value = null;
} catch(ex) { }
if (ctrl.value) {
ctrl.parentNode.replaceChild(ctrl.cloneNode(true), ctrl);
}
},
sendFile() {
var vm = this;
if(this.file !== '') {
this.$http.post('http://localhost:3000/upload',{params: vm.file, headers: {'Content-Type': 'multipart/form-data'}})
.then(response => {
// JSON responses are automatically parsed.
//
}, error => {
//this.errors.push(e)
});
}
}
}
}
</script>
on my server side i am receiving undefined, i don't really know why, i just wanna see if i really got any file in the server, and if yes i want to save it on the server side, any help with that?
i just did this on the /upload endpoint:
router.post('/upload',function(req,res) {
console.log(res.body);
})
You will get Files object from input which is not the actual file but a special reference to a file, you need to useFileReader or FormData to get the actual file and send it, try something like this
var data = new FormData();
var pdf = e.target.files[0];
data.append('file',pdf)
this.$http.post('http://localhost:3000/upload',{params: data}, headers: {'Content-Type': 'multipart/form-data'}})
Related
i'm writing a upload page using filepond. The problem i'm facing is to get it to work like i want. I need to get the metadata from the input and post it with additional formdata
I can allready post the image and additional formdata. However I also want the metadata from the input. If I use onaddfile and log the metadata it works and shows additional="1"
<input type="file" id="img" name="img" data-file-metadata-additional="1">
pond=FilePond.create(document.querySelector('#img'),{
server: {
process: {
url: 'opbouw/model/post/addimg.php',
ondata: (formData) => {
// > POST META DATA
formData.append('userid', '2');
formData.append('usercom', '1');
return formData;
}
}
},
});
pond.onaddfile = (err, item) => {
console.log(item);
const metadata = item.getMetadata();
console.log(metadata);
}
So no clue how to post the metadata
If you're not going to write a custom server.process method then you're going to have to "remember" which metadata belongs to which file.
Something like this:
<input type="file" id="img" name="img" data-file-metadata-additional="1">
<script>
let pondMetadata;
const pond = FilePond.create(document.querySelector('#img'), {
server: {
process: {
url: 'opbouw/model/post/addimg.php',
ondata: (formData) => {
// add metadata
formData.append('usermeta', JSON.stringify(pondMetadata));
formData.append('userid', '2');
formData.append('usercom', '1');
return formData;
}
}
},
onaddfile: (err, item) => {
pondMetadata = item.getMetadata();
}
});
</script>
I'm really lost when it comes to file uploading in meteor and manage the data between client and server.
I'm using Meteor Files from Veliov Group to upload multiple images on the client side. They're getting stored in a FilesCollection called Images and I have my Mongo.Collection called Adverts.
collections.js:
Adverts = new Mongo.Collection('adverts');
Images = new FilesCollection({
collectionName: 'Images',
storagePath: () => {
return `~/public/uploads/`;
},
allowClientCode: true, // Required to let you remove uploaded file
onBeforeUpload(file) {
// Allow upload files under 10MB, and only in png/jpg/jpeg formats
if (file.size <= 10485760 && /png|jpg|jpeg/i.test(file.ext)) {
return true;
} else {
return 'Limit 10mb';
}
}
});
// if client subscribe images
if (Meteor.isClient) {
Meteor.subscribe('files.images.all');
};
// if server publish images
if (Meteor.isServer) {
Images.allowClient();
Meteor.publish('files.images.all', () => {
return Images.collection.find();
});
};
What I'm trying to achieve is, when I upload the images, I wanna store the URLs on the document in Adverts that I'm working with (I'm using iron:router to access those documents _id).
I managed to get the URL but only for the first image uploaded, my code for what I saw on the docs:
Template.imageUpload.helpers({
imageFile: function () {
return Images.collection.findOne();
},
myImage: () => {
console.log(Images.findOne({}).link())
}
})
Template.imageUpload.events({
'change #fileInput': function (e, template) {
if (e.currentTarget.files) {
_.each(e.currentTarget.files, function (file) {
Images.insert({
file: file
});
});
}
}
})
I was using a Meteor.Call to send the URL to the server, but I couldn't manage to update the document with a new property pic and the value url of the image
server.js:
imageUpload: (actDoc, imgURL) => { // actDoc is the document id that I'm working on the client
Adverts.update({'reference': actDoc}, {$set: {'pic': imgURL}})
},
This is probably a dumb question and everything might in the docs, but I've readed those docs back and forth and I can't manage to understand what I need to do.
The answer for my problem was to do it server side
main.js server
FSCollection.on('afterUpload'), function (fileRef) {
var url = 'http://localhost:3000/cdn/storage/images/' + fileRef._id + '/original/' + fileRef._id + fileRef.extensionWithDot;
}
MongoCollection.update({'_id': docId}, { $set: {url: imgUrl }}})
When I want to upload an image and send the other data using FormData. Axios seems to serialize the image. Therefore, when i upload the image using Axios, the image is inside the body's payload as a string. As a result, I'm unable to use Multer on the server side to retrieve the uploaded image from the request.
This is my Vue code:
export default () {
name: 'app',
data () {
image: ''
},
methods: {
onFileChange (e) {
var files = e.target.files || e.dataTransfer.files
if (!files.length) {
return
}
// console.log(files[0])
// var x = files[0]
return this.createImage(files[0])
// return new Buffer(x)
},
createImage (file) {
// var image = new Image()
var reader = new FileReader()
var vm = this
reader.onload = (e) => {
// vm.image = e.target.result
vm.image = file.toString('base64')
console.log(vm.image)
}
reader.readAsDataURL(file)
},
submitStaff () {
const formData = new FormData()
formData.append('file', this.image)
formData.append('name', this.data.name)
formData.append('username', this.data.username)
formData.append('password', this.data.password)
axios.post('api/myApiUrl', formData)
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
}
}
<input type="file" #change="onFileChange">
Request Payload (Error with Vue)
Request Payload (Successful with Postman)
How do i fix this? Thank you!
I faced a problem related to it and in my case I was setting Content-Type as a default configuration for all my requests, doing this:
axios.defaults.headers.common['Content-Type'] = 'application/json [or something]';
And, as I remember, part of my solution was to remove this configuration to make the upload works. I just erased that line from my code and all requests worked well. As soon I removed it, I could notice that my headers request changed to this (see attached image and notice the Content-Type entry):
Another thing you should be alert is the field name to your <input type="file" name="file">. I have a java backend expecting a parameter named as "file", so, in my case, my input file HAS to be set as "file" on my HTML and on my server side, like this:
public ResponseEntity<Show> create(
#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) { ... }
Observe the entry #RequestParam("file")...
And in the HTML file:
<form enctype="multipart/form-data" novalidate v-if="isInitial || isSaving">
<div class="well">
<div class="form-group">
<label>* Selecione o arquivo excel. O sistema fará o upload automaticamente!</label>
<div class="dropbox">
<input type="file" single name="file" :disabled="isSaving" #change="filesChange($event.target.name, $event.target.files); fileCount = $event.target.files.length"
accept="application/vnd.ms-excel" class="input-file">
<p v-if="isInitial">
Solte o arquivo excel aqui<br> ou clique para buscar.
</p>
<p v-if="isSaving">
Carregando arquivo...
</p>
</div>
</div>
</div>
</form>
You also can take a look at this tutorial, it my help you: https://scotch.io/tutorials/how-to-handle-file-uploads-in-vue-2
I hope it helps you!
In my nativescript app, I'm able to record a video, but I want to upload it to an S3 bucket for later streaming. I'm running a node js server that handles the api for my app.
I'm trying to use the 'nativescript-background-http' library, but it always breaks when I try to run the uploadFile function.
Here's the relevant code:
var uploadVideo = function (filepath) {
console.log("Attempting to upload video...");
var session = bghttp.session("video-upload");
var filename = filepath.replace(/^.*[\\\/]/, '');
var request = {
url: config.apiUrl + 'upload',
method: "POST",
headers: {
"Content-Type": "video/mp4",
"File-Name": filename
},
description: "{ 'uploading': filename }"
};
try {
var task = session.uploadFile(filepath, request);
task.on("progress", logEvent);
task.on("error", logEvent);
task.on("complete", logEvent);
function logEvent(e) {
console.log("Logging event.");
console.dir(e);
console.log(e.eventName);
}
}
catch (error) {
console.dir(error);
console.log("An error occurred uploading the file. Removing video from filesystem...");
var documents = fs.knownFolders.documents();
var file = documents.getFile(filename);
file.remove()
.then(function (result) {
console.log("The video has been removed successfully.");
}, function (error) {
console.log("The video could not be removed from the file system.");
console.dir(error);
});
}
};
This is the output I end up with:
JS: Video located at /data/user/0/org.nativescript.Lifey/files/videoCapture_1486072596043.mp4
JS: Attempting to upload video...
JS: === dump(): dumping members ===
JS: {
JS: "nativeException": {
JS: "constructor": "constructor()function () { [native code] }"
JS: }
JS: }
JS: === dump(): dumping function and properties names ===
JS: === dump(): finished ===
JS: An error occurred uploading the file. Removing video from filesystem...
JS: The video has been removed successfully.
Any idea what's going on? Does 'nativescript-background-http' library even support video uploads (I've only seen image upload examples on their github)? Is there some alternative that I could use if I can't use that library?
Why isn't it displaying a file record in my template? The only thing it returns to the template is just the 'cursor' object.
What the console.log(file) output is in the JS console:
FilesCollection {collectionName: "Files", downloadRoute: "/cdn/storage", schema: Object, chunkSize: 524288, namingFunction: false…}
I've looked at every post, etc. I realize it returns a cursor to the client, but I'm doing a Files.findOne() query, which should return the record itself to the template / html.
'/imports/api/files.js'
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
export const Files = new FilesCollection({
collectionName: 'Files',
allowClientCode: false, // Disallow remove files from Client
onBeforeUpload: function (file) {
// Allow upload files under 10MB, and only in png/jpg/jpeg formats
if (file.size <= 10485760 && /png|jpg|jpeg/i.test(file.extension)) {
return true;
} else {
return 'Please upload image, with size equal or less than 10MB';
}
}
});
if (Meteor.isServer) {
// This code only runs on the server
Meteor.publish('getFile', function(id) {
return Files.find({_id: id }).cursor;
});
}
'/imports/ui/components/download.js'
import './download.html';
import { Files } from '../../api/files.js';
Template.download.onCreated(function() {
let self = this;
self.autorun(function() {
let fileId = FlowRouter.getParam('id');
self.subscribe('getFile', fileId);
});
});
Template.download.helpers({
file: function () {
let fileId = FlowRouter.getParam('id');
let file = Files.findOne({_id: fileId}) || {};
console.log(file)
return file;
}
});
'/imports/ui/components/download.html'
<template name='download'>
{{#if Template.subscriptionsReady}}
{{#with file}}
<a href="{{link}}?download=true" download="{{name}}" target="_parent">
{{name}}
</a>
<p>{{link}}</p>
<h1>subscriptions are ready!</h1>
<h2>{{collectionName}}</h2>
{{/with}}
{{else}}
<p>Loading...</p>
{{/if}}
</template>
World's dumbest mistake, remember: template names in Meteor must be in Upper case!