I'm using Vue with NodeJs, Vuetify and Express. I load user's file with the Vuetify's component:
<v-file-input
v-model="documentFile.value"
:error-messages="documentFile.errors"
accept="application/pdf"
/>
Then I want to pass the file (that is stored in this.documentFile.value) to my backend, so it will upload it to the Drive. I pass the data using Vue Recourse:
var params = {
"data": this.data.value
"score": this.score.value
//"document_file": this.documentFile.value,
"comments": this.comments.value
};
Vue.http.put('http://localhost:8081/api/new-document', {params: params}).then(
response => {
console.log("Sent data");
}, response => {
console.error(response);
}
);
In my NodeJS backend I have:
router.put('/new-document', function(request, response) {
console.log("New Document");
console.log(request.query);
// Upload file to drive
const oauth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URI
);
response.status(200).send({});
});
How can I pass the file from the client to the backend?
EDIT: If I uncomment document_file, and try to print request.query, it prints:
{
data: { age: '27', name: 'robert' },
comments: 'comment',
"score": 89
}
For some reason, it ignores the document_file.
The code in my server.js:
const cors = require("cors");
const express = require("express");
const bodyParser = require("body-parser");
const routes = require('./routes');
const path = __dirname + '/../public/';
console.log("STARTED");
const app = express();
app.use(express.static(path));
var corsOptions = {
origin: "http://localhost:8080"
};
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// map requests to routes
app.use('/api', routes);
// set port, listen for requests
const PORT = process.env.PORT || 8081;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
To pass the file from the client to the backend, use the new FormData() object.
In your case you can do something like:
var params = new FormData();
params.append('data', this.data.value);
params.append('score', this.score.value);
params.append('document_file', this.documentFile.value)
params.append('comments', this.comments.value);
Then pass the object either using axios or Vue Recourse as you would like.
axios.put('url', params)
EDIT
You can use multer to upload your files either locally or to the cloud. In your case, you can upload to GoogleStorage
const multer = require('multer')
// You can start off by testing local uploads
const upload = multer({ dest: 'uploads/' })
// then use this to upload to Google Storage
const multerGoogleStorage = require('multer-google-storage')
const uploadHandler = multer({
storage: multerGoogleStorage.storageEngine({
autoRetry: true,
bucket: '<your_storage_bucket_name>',
projectId: '<your_project_ID>',
keyFilename: '<your_path_to_key_file>',
filename: (req, file, cb) => {
cb(null, `/<some_prefix_of_choice>/${Date.now()}_${file.originalname}`)
}
})
})
Upload the file either to local or Google Cloud
// local uploads (destination projectRoot/uploads)
router.put('/new-document', upload.single('document_file'), async (request, response) => {});
// or GoogleStorage
router.put('/new-document', uploadHandler.single('document_file'), async (request, response) => {});
Multiple files can also be uploaded
app.put('/new-document', upload.array('document_files', 12), function (req, res, next) {
// req.files is array of `photos` files
// req.body will contain the text fields, if there were any
})
The document file(s) can then be accessible on the Express server using
request.file
You can the upload the file. The other form objects can also be accessible through request.body e.g.
request.body.data