I'm a beginner when it comes to using Uppy. I'm sure that this can be resolved by pros like you. But I am having trouble sending specific meta data information to my upload route.
uppy.js
// Import the plugins
const Uppy = require('#uppy/core');
const XHRUpload = require('#uppy/xhr-upload');
const Dashboard = require('#uppy/dashboard');
const request = require('request');
const uppy = Uppy({
debug: true,
autoProceed: false,
restrictions: {
maxFileSize: 1024000,
maxNumberOfFiles: 3,
minNumberOfFiles: 1,
allowedFileTypes: ['image/*', 'video/*']
}
})
.use(Dashboard, {
trigger: '.UppyModalOpenerBtn',
inline: true,
target: '#drag-drop-area',
replaceTargetContent: true,
showProgressDetails: true,
proudlyDisplayPoweredByUppy: false,
animateOpenClose: true,
note: 'Images and video only, 1–3 files, up to 1 MB',
height: 470,
browserBackButtonClose: true,
theme: 'dark',
metaFields: [
{id: 'caption', name: 'Caption', placeholder: 'describe what the image is about'}
]
});
uppy.on('file-added', (file) =>{
console.log(file);
uppy.setFileMeta(file.meta.id, {
caption: file.name
});
});
uppy.use(XHRUpload, {
id: 'XHRUpload',
endpoint: 'http://localhost:8000/upload',
method: 'POST',
formData: true,
fieldName: 'my_file',
metaFields: ['caption'],
bundle: true
});
uppy.on('upload-success', (file, response) => {
//console.log(file.meta.caption);
console.log("File uploaded successfully ", file);
});
module.exports = uppy;
upload.js
router.post('/',(req, res, next) => {
console.log("Coming form uppy.js " , req.body);
});
module.exports = router;
I'm having trouble passing the 'caption' value to my route. When I look on the 'network tab' on Google Chrome's developer tools, it give me a message of 'undefined'. If you can point me at the right direction, I'd appreciate it! Thank you!
First of all need to change file.meta.id to file.id
uppy.on('file-added', (file) =>{
console.log(file);
uppy.setFileMeta(file.id, {
test: 'hello'
});
});
but if you use bundle you should know about that note
Note: When bundle is set to true, only global uppy metadata, the one set via meta options property, is sent to the endpoint. Individual per-file metadata is ignored.
so, if you want send meta data for each file you should change it to false, then you faced with separate request for each file, but all meta data would be present in request
Related
Im using this code to stream into a file. But the created file is empty. Is there something wrong with my code?
const fileStream = pinoms.prettyStream(
{
prettyPrint: {
colorize: true,
levelFirst: true,
translateTime: "yyyy-dd-mm, h:MM:ss TT",
},
},
pinoms.destination({
dest: './my-file', // omit for stdout
minLength: 4096, // Buffer before writing
sync: true}) // Asynchronous logging)
)
const streams = [
{stream: fileStream}
]
const logger = pinoms(pinoms.multistream(streams))
logger.info('HELLO %s!', 'World')
In the documentation it says:
const prettyStream = pinoms.prettyStream(
{
prettyPrint:
{ colorize: true,
translateTime: "SYS:standard",
ignore: "hostname,pid" // add 'time' to remove timestamp
},
prettifier: require('pino-pretty') // not required, just an example of setting prettifier
// as well it is possible to set destination option
}
);
So it should be possible.
PS: I know there is the option to put a writestream with fs into it but I want to get the time formatted.
I found a practicable solution for me. Scince v 7 pino provides the multistream function by it selve. Now I can do all I wanted to do. Using destination and also make the timestamp pretty.
const streams = [
{stream: pino.destination('test.log')},
{stream: pretty({
colorize: true,
sync: true,
})}
]
const logger = pino({level: 'info', timestamp: pino.stdTimeFunctions.isoTime}, pino.multistream(streams))
logger.info('HELLO %s!', 'World')
I want to do the same feature as found in this SO Post ;
But in the onStatusChange callback the objects are null.
callbacks: {
onStatusChange: function(id, oldStatus, newStatus) {
console.log('new status of ' + newStatus + ' for ID: ' + id);
console.log(this.getItemByFileId(id));
}
I get the following output
new status of upload successful for ID: 0
fine-uploader.min.js:2 [Fine Uploader 5.14.2] Caught exception in 'onStatusChange' callback - Cannot read property 'className' of null
I know session response from my server is OK, b/c fine-uploader displays my file, filename and the delete button.
Is what I'm trying to do supported?
Here's my full fine-uploader code for reference:
`
var uploader_132963 = new qq.FineUploader({
element: document.getElementById("uploader_132963"),
session: { endpoint: 'https://localhost/session', params : { account: 'DEMO9', index: 1, psuuid: UUID_UPLOAD1},},
template : 'qq-template1',
debug: true,
request : {
endpoint: 'localhost',
},
autoUpload: true,
retry: {
enableAuto: true
},
multiple: false,
concurrent: {
enabled: false
},
chunking: {
concurrent: {
enabled : false,
},
enabled: true,
mandatory: true,
partSize: 2000000,
success: {
endpoint: 'https://localhost/success'
}
},
deleteFile: {
enabled: true,
endpoint: 'https://localhost',
method: 'POST',
},
extraButtons: {
folders: false
},
validation: {
allowedExtensions: ['3g2','asf','avi','bmp','doc','docx','flv','gif','jpeg','jpg','m4a','m4v','mj2','mov','mp3','mp4','pdf','png','ppt','pptx','svg',],
allowEmpty: false,
itemLimit: 1,
sizeLimit: 1024000000,
},
callbacks: {
onStatusChange: function(id, oldStatus, newStatus) {
if (newStatus == qq.status.UPLOAD_SUCCESSFUL) {
var fileItem = this.getItemByFileId(id); // will throw exception here
}
}
}
})
`
I had the exact same issue as described here. The solution was as pointed out by bobflorian. This is how I handle both canned files loaded from the server normal uploaded files:
onAllComplete: function( arrSucceeded, arrFailed,) {
if (arrSucceeded!==null && $.isArray(arrSucceeded)){
for (var i=0,x=arrSucceeded.length;i<x;i++){
//Get the template markup for the uploaded file
var fileItem = this.getItemByFileId(arrSucceeded[i]);
//Get the generated uuid. This is the same uuid that we save in the PHP SESSION. It points to the actual uploaded file
var uuid = this.getUuid(arrSucceeded[i]);
}
}
}
I'm using version 5.16.2. Ray, you did a fantastic job with this library.
Moving my code to the onAllComplete callback gives the desired result when loading files via the Initial File List. The onStatusChange doesn't seem to have the getItemByFileId function available under this at that point in time. It will throw an exception of
Caught exception in 'onStatusChange' callback - Cannot read property 'className' of null
I am building an electron app which handles file uploads, I am using dialog to get the files from user, I need to send the files to server but I am getting the files path but I get errors when sending them . I am using Vue resource for requests. Below is my code:
<template>
<div>
<button #click="uploadAct()" class="primary">New Upload </button>
</div>
</template>
<script>
const {dialog} = require('electron').remote
const fs = require('fs')
import reqApi from '../../api/something'
export default {
methods: {
uploadAct () {
dialog.showOpenDialog({
title: 'Upload Attachments',
buttonLabel: 'Upload',
filters: [
{name: 'Images', extensions: ['jpg', 'png', 'gif']},
{name: 'All Files', extensions: ['*']}
],
properties: ['openFile', 'multiSelections']
}, function (filenames) {
if (filenames) {
let d = ''
filenames.forEach(function (element) {
d = element
})
// here i get a path of file correctly something like /path/to/file.jpg
reqApi.uploadattachmnets({photo: fs.createReadStream(d)}).then(
(response) => {
console.log(response)
},
(error) => {
console.log(error)
})
// })
}
})
}
}
}
</script>
I however end up with error on the request , any help will be appreciated .
Probably a typo but you have a call to an API:
carApi.uploadattachmnets({photo: fs.createReadStream(d)})
which is different to the one you are importing:
import reqApi from '../../api/something'
If not the above I'd assume this is going to be a CORS issue if Postman is already able to send files and receive the correct response from the endpoint. Without more info I'd recommend looking at: https://www.html5rocks.com/en/tutorials/cors/#toc-making-a-cors-request
For a more specific response you'd need to post the API code so we can review how you are sending the file.
I intend to download a dynamically generated pdf file using a remote method, the file exists at a particular path and I am using return type "file". My implementation is:
customer.downloadFile = function downloadFile(userId, res, cb){
var reader = fs.createReadStream(__dirname + '/../document.pdf');
cb(null, reader, 'application/pdf');
};
customer.remoteMethod(
'downloadFile',
{
isStatic: true,
accepts: [
{ arg: 'id', type: 'string', required: true },
{ arg: 'res', type: 'object', 'http': { source: 'res' } }
],
returns: [
{ arg: 'body', type: 'file', root: true },
{ arg: 'Content-Type', type: 'string', http: { target: 'header' } }
],
http: {path: '/:id/downloadFile', verb: 'get'}
}
);
The issue with the above code is that the browser although displays the beautiful pdf file container, but instead of the file following error is shown:
Please point out as to what is wrong with the code and how to correct.
Got lead from this URL: https://github.com/strongloop/loopback-swagger/issues/34
Got that working with following:
fs.readFile(fileName, function (err, fileData) {
res.contentType("application/pdf");
res.status(200).send(fileData);
if (!err) {
fs.unlink(fileName);
}
else {
cb(err);
}
});
You should use loopback-component-storage to manage downloadable files.
Files are grouped in so-called containers (Basically, a folder with a single level of hierarchy, not more).
How it is done:
Create a model called container for instance.
Create a storage datasource that uses as connector the loopback-component-storage
Give to container model the datasource storage
That's it. You can upload and download files to/from your container.
With a container, you can store files to a local filesystem, or move later to Cloud solutions.
i have a grid with an toolbar and on that toolbar an upload option is added, so the upload is alright and it works , but after the file was uploaded to the server the success function does not react.
here my upload code:
upload: function () {
Ext.create('Ext.window.Window', {
title: 'Upload',
width: 300,
layout: 'fit',
draggable: false,
resizable: false,
modal: true,
bodyPadding: 5,
items: [{
xtype: 'form',
bodyPadding: 10,
frame: true,
items: [{
xtype:'filefield',
name:'file',
fieldLabel: 'File',
buttonText: 'Select File',
labelWidth: 30,
anchor: '100%'
}, {
xtype: 'button',
text: 'Upload',
handler: function(){
var form = this.up('form').getForm();
if(form.isValid()){
form.submit({
method: 'POST',
url: 'http://localhost:3000/upload',
success: function (form, action) {
Ext.Msg.alert('Success', 'Your File has been uploaded.');
console.log(action);
},
failure : function (form,action) {
Ext.Msg.alert('Error', 'Failed to upload file.');
}
})
}
}
}]
}],
}).show();
},
});
and the server response :
app.post('/upload', function(req, res) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Content-Type','application/json; charset=UTF8');
var tmp_path = req.files.file.path;
var newPath = __dirname + '/files/' + req.files.file.name;
fs.rename(tmp_path, newPath, function (err){
if (err) throw err;
});
var path = newPath;
var name = req.files.file.name;
connection.query('SELECT name FROM audio WHERE name = ?', [name] , function(err,result) {
if (result[0]) {
console.log('File already exist');
res.status(400).send(JSON.stringify());
} else {
connection.query('INSERT INTO audio (name, path) VALUES (?,?)', [name,path], function (err,result) {
if (err) throw err;
var test = {
success: true
};
res.send({success:true});
console.log('success');
});
}
});
});
i can provide more code if necessary, thanks in advance
The error message is explicit: your response is lost due to cross-domain iframe issue.
See the doc explanation of how file upload form are handled: a hidden iframe is created to receive the response from the server (because, before HTML5 it was not possible to upload a file using XHR). When the iframe is loaded, Ext parses its content to read the response.
But, it is only allowed for a page to manipulate its iframes content if both are on the same domain, including the port number.
Most probably you're accessing your page at http://localhost/, while you're posting your form to http://localhost:3000. So forbidden: error, and no response for you!
This is a Ext js bug identified by Uberdude in the Sencha Forum.
Description of the problem :
When you make an Ext.Ajax.request with a form containing a file input to be uploaded, or manually set the isUpload option to true, rather than doing a proper Ajax request Ext submits the form in the standard HTML way to a dynamically generated hidden . The json response body is then read out of the iframe to create a faked-up Ajax response. A problem arises if the page making the upload Ajax request has changed its document.domain property, e.g. a page at home.example.com includes resources from static.example.com which it wishes to manipulate with javascript without violating the browser's same-origin-policy, so both set their document.domain to "example.com". If home.example.com then makes an upload Ajax request to a url on the home.example.com server, the iframe into which the response is written will have its document.domain as "home.example.com". Thus when the ExtJS code within Ajax.request on the home.example.com page tries to extract the document body from the iframe, it will be blocked by the same-origin-policy and the response passed to the callback functions will incorrectly have empty responseText.
Work Around :
1. Pass the document.domain to the server when making the upload request.
2. In your server response, add the document.domain in your response text/html.
response.setHeader('Content-Type', 'text/html');
response.write('document.domain = "' + params.__domain + '";');
response.write(JSON.stringify({msg: 'Welcome ' + params.name}));
response.end('');
Detail :
Please refer to :
http://www.sencha.com/forum/showthread.php?136092-Response-lost-from-upload-Ajax-request-to-iframe-if-document.domain-changed