[filepond]To register with the ID value serverId received from the server - javascript

'filepond' is being used in vue. But there's a problem.
In "process",
The ID value was returned after the file was transferred to the server. (response.id) If you register this as 'serverId' of file and check 'file' as console, it is registered normally.
mounted() {
setOptions({
server: {
process: (fieldName, file, metadata, load, error, progress, abort) => {
const formData = new FormData();
formData.append('mainData', file);
createmainData(formData, {
onUploadProgress: (event) => {
progress(event.lengthComputable, event.loaded, event.total);
}
})
.then(response => {
const serverId = response.id
file.serverId = serverId
load(response, serverId)
})
.catch(error => {
console.log(error);
error('Error uploading file');
})
console.log (file)
},
},
});
}
But if you run 'updatefiles' methods and check 'files' as a console,
It says 'serverId: undefined'.
methods: {
updatefiles(files) {
this.files = files.map(files => files.setMetadata);
console.log('files',files )
},
},
If you look at the comments left by the producers,
I tried, but I keep failing, maybe I'm misunderstanding.
Can you tell me the solution?

You have to push serverId to separate array (i.e. uploadedFiles) in the process after the file was successfully transfered to the server. I can't see this in your code. With this array you will be able to manage FilePond content and order of uploaded files.
handleFilePondInit() {
this.uploadedFiles = [];
},
handleFilePondLoad(response) {
this.uploadedFiles.push(response);
return response;
},
handleFilePondUpdate(files, origin, target) {
this.uploadedFiles = files.map(files => files.serverId);
this.uploadedFiles = this.item.uploadedFiles.filter(element => { return element !== null; });
},

Related

throw er; // Unhandled 'error' event Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

i tried to upload product (including the image), i used the same code on this video https://www.youtube.com/watch?v=GCmjLIEtJbA&t=206s, but its failed to upload product ?, but the server give me a 200 res, then the express app goes crash, could you help me with this issues ??
this is my UploadPage component (React) :
const onSubmit = (event) => {
event.preventDefault();
// send data to server
const variables = {
writer: props.user.userData._id,
title: TitleValue,
description: DescriptionValue,
price: PriceValue,
images: Images,
continents: ContinentValue,
};
Axios.post("/api/product/uploadProduct", variables).then((response) => {
if (response.data.success) {
alert("Successfully to upload product");
props.history.push("/");
} else {
alert("Failed to upload product");
}
});
};
and here for the product route (Express) :
router.post("/uploadProduct", auth, (req, res) => {
// save all data from the client to database
const product = new Product(req.body);
product.save((err) => {
// if fail
if (err) {
return res.status(400).json({ success: false, err });
}
// if success
return res.json(200).json({ success: true });
});
});
here's also my FileUpload component (React) :
const onDrop = (files) => {
let formData = new FormData();
const config = {
header: {
"content-type": "multipart/form-data",
},
};
formData.append("file", files[0]);
// save the image inside the node server
Axios.post("/api/product/uploadImage", formData, config).then(
(response) => {
if (response.data.success) {
setImages([...Images, response.data.image]);
props.refreshFunction([...Images, response.data.image]);
} else {
alert("Failed to save the Image in server");
}
}
);
};
did the front end messed up the back end ?,
Thanks, sorry for my bad english.
Solved by myself, somewhere in my (Express) code there is a code like this:
const storage = multer.diskStorage({
// where i want to save the file
destination: (req, file, cb) => {
cb(null, "uploads/");
},
// more code
});
then i change it into :
const storage = multer.diskStorage({
// where i want to save the file
destination: (req, file, cb) => {
cb(null, "./uploads/");
},
// more code
});

Making a distinction between file not present and access denied while accessing s3 object via Javascript

I have inherited the following code. This is part of CICD pipeline. It tries to get an object called "changes" from a bucket and does something with it. If it is able to grab the object, it sends a success message back to pipeline. If it fails to grab the file for whatever reason, it sends a failure message back to codepipeline.
This "changes" file is made in previous step of the codepipeline. However, sometimes it is valid for this file NOT to exist (i.e. when there IS no change).
Currently, the following code makes no distinction if file simply does not exist OR some reason code failed to get it (access denied etc.)
Desired:
I would like to send a success message back to codepipeline if file is simply not there.
If there is access issue , then the current outcome of "failure' would still be valid.
Any help is greatly appreciated. Unfortunately I am not good enough with Javascript to have any ideas to try.
RELEVANT PARTS OF THE CODE
const AWS = require("aws-sdk");
const s3 = new AWS.S3();
const lambda = new AWS.Lambda();
const codePipeline = new AWS.CodePipeline();
// GET THESE FROM ENV Variables
const {
API_SOURCE_S3_BUCKET: s3Bucket,
ENV: env
} = process.env;
const jobSuccess = (CodePipeline, params) => {
return new Promise((resolve, reject) => {
CodePipeline.putJobSuccessResult(params, (err, data) => {
if (err) { reject(err); }
else { resolve(data); }
});
});
};
const jobFailure = (CodePipeline, params) => {
return new Promise((resolve, reject) => {
CodePipeline.putJobFailureResult(params, (err, data) => {
if (err) { reject(err); }
else { resolve(data); }
});
});
};
// MAIN CALLER FUNCTION. STARTING POINT
exports.handler = async (event, context, callback) => {
try {
// WHAT IS IN changes file in S3
let changesFile = await getObject(s3, s3Bucket, `lambda/${version}/changes`);
let changes = changesFile.trim().split("\n");
console.log("List of Changes");
console.log(changes);
let params = { jobId };
let jobSuccessResponse = await jobSuccess(codePipeline, params);
context.succeed("Job Success");
}
catch (exception) {
let message = "Job Failure (General)";
let failureParams = {
jobId,
failureDetails: {
message: JSON.stringify(message),
type: "JobFailed",
externalExecutionId: context.invokeid
}
};
let jobFailureResponse = await jobFailure(codePipeline, failureParams);
console.log(message, exception);
context.fail(`${message}: ${exception}`);
}
};
S3 should return an error code in the exception:
The ones you care about are below:
AccessDenied - Access Denied
NoSuchKey - The specified key does not exist.
So in your catch block you should be able to validate exception.code to check if it matches one of these 2.

How can i add values from the front end to a json file in a react application?

I have built a react application where I have created a file upload mechanism. Now along with the file upload there are three dropdowns 'Controller','Test' and 'Protocol'. Now along with the file upload to the server functionality I am enabling the user to add the values to the dropdown from the front-end itself. I have enforced few validations on the file which is getting uploaded and then
I am adding the controller, test and protocol based on the file name. SO for instance if the filename of the uploaded file is "abc_xyz_sas_uut.config" which is the variable Filename in the script then the three fields 'Controller','Test' and 'Protocol' should only accept 'abc','xyz' and 'sas' as the respective values.
I have written the below script but its getting me an error 'Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client'. The problem is I guess that its setting the status twice. Can anyone help to fix this issue, any help is greatly appreciated as I am stuck at this point.
class FileUpload extends Component {
state = {
file: "",
fileName: "Choose File",
uploadDisabled: true,
controller: "",
test: "",
protocol: "",
};
handleFileChange = (e) => {
let index = e.target.files[0].name.search(/\w+[_]\w+[_]\w+[_]uut.yaml-example/i);
if (index === 0) {
this.setState({ file: e.target.files[0] });
this.setState({ fileName: e.target.files[0].name });
this.setState({ uploadDisabled: false });
} else {
window.alert(
"File name or format is not correct ! \nCorrect format is controller_test_protocol_uut.yaml-example"
);
}
e.target.value = null;
};
handleUpload = async (e) => {
console.log("Starting upload");
const formData = new FormData();
formData.append("file", this.state.file);
formData.append("controller", this.state.controller);
formData.append("test", this.state.test);
formData.append("protocol", this.state.protocol);
try {
const res = await axios.post(this.props.url + "/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
const { status } = res.data;
if (status === "ok") {
this.props.refreshOptions();
this.setState({ file: "" });
this.setState({ fileName: "Choose File" });
this.setState({controller : ""});
this.setState({test : ""});
this.setState({protocol : ""});
alert("File Uploaded Successfully");
document.getElementById("closeButton").click();
}
} catch (err) {
console.log(err);
}
};
handleTextChange = (e) => {
this.setState({ ...this.state, [e.target.id]: e.target.value });
};
You have a res.json() statement in your else-block:
//Writing Config back to disk
}
else {
res.json({
status: "Invalidvalues"
});
}
and right after
res.json({
status: "ok"
});
So in case of hitting the else block res.json() is executed twice which is probably the cause for the error. You should change the statement in the else block to:
return res.json({
status: "Invalidvalues"
});

How to get file properties and upload a file from ionic 4?

I am trying to upload a file from mobile to google bucket using ionic 4. Although a file can upload into the could. I am struggling to get the file properties out of file object.
Here is my method,
async selectAFile() {
const uploadFileDetails = {
name: '',
contentLength: '',
size: '',
type: '',
path: '',
};
this.fileChooser.open().then(uri => {
this.file.resolveLocalFilesystemUrl(uri).then(newUrl => {
let dirPath = newUrl.nativeURL;
const dirPathSegments = dirPath.split('/');
dirPathSegments.pop();
dirPath = dirPathSegments.join('/');
(<any>window).resolveLocalFileSystemURL(
newUrl.nativeURL,
function(fileEntry) {
uploadFileDetails.path = newUrl.nativeURL;
const file: any = getFileFromFileEntry(fileEntry);
//log 01
console.log({ file });
uploadFileDetails.size = file.size;
uploadFileDetails.name = `${newUrl.name
.split(':')
.pop()}.${file.type.split('/').pop()}`;
uploadFileDetails.type = file.type;
async function getFileFromFileEntry(fileEntry) {
try {
return await new Promise((resolve, reject) =>
fileEntry.file(resolve, reject)
);
} catch (err) {
console.log(err);
}
}
},
function(e) {
console.error(e);
}
);
});
});
// here uploadFileDetails is simller to what I declared at the top ;)
// I wan't this to be populated with file properties
// console.log(uploadFileDetails.name) --> //''
const uploadUrl = await this.getUploadUrl(uploadFileDetails);
const response: any = this.uploadFile(
uploadFileDetails,
uploadUrl
);
response
.then(function(success) {
console.log({ success });
this.presentToast('File uploaded successfully.');
this.loadFiles();
})
.catch(function(error) {
console.log({ error });
});
}
even though I can console.log the file in log 01. I am unable to get file properties like, size, name, type out of the resolveLocalFileSystemURL function. basically, I am unable to populate uploadFileDetails object. What am I doing wrong? Thank you in advance.
you actually need 4 Ionic Cordova plugins to upload a file after getting all the metadata of a file.
FileChooser
Opens the file picker on Android for the user to select a file, returns a file URI.
FilePath
This plugin allows you to resolve the native filesystem path for Android content URIs and is based on code in the aFileChooser library.
File
This plugin implements a File API allowing read/write access to files residing on the device.
File Trnafer
This plugin allows you to upload and download files.
getting the file's metadata.
file.resolveLocalFilesystemUrl with fileEntry.file give you all the metadata you need, except the file name. There is a property called name in the metadata but it always contains value content.
To get the human readable file name you need filePath. But remember you can't use returning file path to retrieve metadata. For that, you need the original url from fileChooser.
filePathUrl.substring(filePathUrl.lastIndexOf('/') + 1) is used to get only file name from filePath.
You need nativeURL of the file in order to upload it. Using file path returning from filePath is not going to work.
getFileInfo(): Promise<any> {
return this.fileChooser.open().then(fileURI => {
return this.filePath.resolveNativePath(fileURI).then(filePathUrl => {
return this.file
.resolveLocalFilesystemUrl(fileURI)
.then((fileEntry: any) => {
return new Promise((resolve, reject) => {
fileEntry.file(
meta =>
resolve({
nativeURL: fileEntry.nativeURL,
fileNameFromPath: filePathUrl.substring(filePathUrl.lastIndexOf('/') + 1),
...meta,
}),
error => reject(error)
);
});
});
});
});
}
select a file from the file system of the mobile.
async selectAFile() {
this.getFileInfo()
.then(async fileMeta => {
//get the upload
const uploadUrl = await this.getUploadUrl(fileMeta);
const response: Promise < any > = this.uploadFile(
fileMeta,
uploadUrl
);
response
.then(function(success) {
//upload success message
})
.catch(function(error) {
//upload error message
});
})
.catch(error => {
//something wrong with getting file infomation
});
}
uploading selected file.
This depends on your backend implementation. This is how to use File Transfer to upload a file.
uploadFile(fileMeta, uploadUrl) {
const options: FileUploadOptions = {
fileKey: 'file',
fileName: fileMeta.fileNameFromPath,
headers: {
'Content-Length': fileMeta.size,
'Content-Type': fileMeta.type,
},
httpMethod: 'PUT',
mimeType: fileMeta.type,
};
const fileTransfer: FileTransferObject = this.transfer.create();
return fileTransfer.upload(file.path, uploadUrl, options);
}
hope it helps. :)

returning status once the file is written to local from s3 bucket

trying to fetch a file from s3 bucket and storing it on the local, once its written to the local reading the file from the local and converting the data to json format and sending it.
i need to check whether the file is downloaded and written to local, once the file exist only read and convert it to json else send an error message.
once the file is on open i am writing the file and making end. So after end i can't send a return value. So how i can solve this one and use try catch to send proper error message.
const fetchFileDownloadAndWriteIt = () => {
let Bucket = "DataBucket";
let filename = "sample_data.csv";
let s3 = new AWS.S3();
const params = {
Bucket: Bucket,
Key: filename
};
return s3.getObject(params)
.promise()
.then(data => {
const file = fs.createWriteStream('./localdata/' + filename);
file.on("open", () => {
file.write(data.Body);
file.end();
})
.on("error", err => {
console.log("Error Occured while writing", err.message)
})
})
.catch(err => {
console.log("unable to fetch file from s3 Bucket", err.message)
})
}
exports.fetchData = async (req,res) => {
let fileDownloadAndWrite = await fetchFileAndDownloadWriteIt();
// need to check file is downloaded and written properly
const path = "./localdata/sample_data.csv";
const json = await csv().fromFile(path);
res.send({data: json})
}
You can return a new Promise instead of the one instead of the one you get by calling the SDK's API.
return new Promise((res, rej) => {
s3.getObject(params)
.promise()
.then(data => {
const file = fs.createWriteStream('./localdata/' + filename);
file
.on("open", () => {
file.write(data.Body);
file.end();
//success
res();
})
.on("error", err => {
rej(err);
})
})
.catch(err => {
rej(err);
})
});
This will resolve to undefined and rejected with the proper error occured, like while writing file, etc.
How to Call it in your handler?
Something like this would be fine.
exports.fetchData = async (req, res, next) => {
try {
await fetchFileDownloadAndWriteIt();
// need to check file is downloaded and written properly - here the file is actually downloaded and written properly.
const path = "./localdata/sample_data.csv";
const json = await csv().fromFile(path);
res.send({ data: json })
}
catch (err) {
return next(err);
}
}

Categories