React: Trying to read custom file consistently leads to index.html - javascript

I am trying to read a user-selected file in my React app, using the following code:
function Entries() {
async function importEntries() {
let file = document.getElementById('file-select').files[0];
let response = await fetch(file);
let textResponse = await response.text();
console.log(textResponse);
}
return (
<div className='Entries'>
<h2>Import entries</h2>
<label htmlFor='file-select'>Select file:</label>
<input type='file' name='file' id='file-select' />
<button onClick={importEntries}>Upload</button>
</div>
);
}
This is somehow consistently giving me the contents of the index.html file in the public directory of my React app, no matter which file I select.
Anyone knows what is causing this?

use then and catch in fetch method
Example :
fetch('http://example.com/movies.json')
.then(response => response.json())
.then(data => console.log(data));
.catch(err => console.log(err))

Is there any reason you're trying to fetch this file? As far as I have seen, you can do something like
async function importEntries() {
let file = document.getElementById('file-select').files[0];
let textResponse = await file.text();
console.log(textResponse);
}
or use a FileReader.
Also, unrelated, you might want to avoid using document.getElementById and useRef instead, like so:
const fileInputRef = useRef();
async function importEntries() {
let file = fileInputRef.current.files[0];
let textResponse = await file.text();
console.log(textResponse);
}
//Later in the code
<input type='file' name='file' ref={fileInputRef} />

Try this:
Replace <input type='file' name='file' id='file-select' /> to <input type='file' name='file' id='file-select' onChange={importEntries}/>
And then replace your importEntries method to this:
async function importEntries(e) {
let file = e.target.files[0];
/* Try this edit */
let reader = new FileReader();
reader.readAsText(file);
reader.onload = function() {
console.log(reader.result);
};
reader.onerror = function() {
console.log(reader.error);
};
}
I haven't tested the code let me know if this worked.

Related

Upload an image from input | JavaScript VueJs

This is the first time I try to upload a file from a client (Vue.js), through a server (Node.js, Express.js) to a database (MongoDB).
I would like to do it without any library.
The logic I'm trying to implement is the following: user can upload a file from an input. This file (can only be an image) is encoded to base64. Then it is sent to the server and recorded in the database as a string. It actually works. Data provided are well recorded in the database. But it also generates these errors:
This error appears just after loading the image in the input.
Theses errors appear just after submitting the form.
<script setup>
import FormInputMolecule from "#/molecules/FormInput.vue";
import ButtonAtom from "#/atoms/Button.vue";
import { computed, ref } from "vue";
import { useRouter } from "vue-router";
import { useSkillStore } from "#/store/skillStore";
import { skillSchema } from "#/validations/skillSchema";
import { validationErrors, validateData } from "#/services/yup";
const router = useRouter();
const skillStore = useSkillStore();
const loading = computed(() => skillStore.loaders.createSkill);
const skillData = ref({
name: null,
image: null,
progress: null,
});
const previewImage = async (event) => {
const preview = document.getElementById("preview-image");
skillData.value.image = event.target.files[0];
if (skillData.value.image) {
const imageUrl = URL.createObjectURL(skillData.value.image);
preview.src = imageUrl;
} else {
preview.src = "";
}
};
const toBase64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
const resetError = (field) => {
if (validationErrors.value.skillCreationForm?.[field]) {
validationErrors.value.skillCreationForm[field] = null;
}
};
const createSkill = async () => {
try {
validationErrors.value["skillCreationForm"] = {};
const isValid = await validateData(
["skillCreationForm"],
skillSchema,
skillData.value
);
if (!isValid) return;
skillData.value.image = await toBase64(skillData.value.image);
skillData.value.progress = parseInt(skillData.value.progress);
await skillStore.createSkill(skillData.value);
console.log(skillData.value);
router.push({ name: "skills" });
} catch (error) {
console.error(error);
}
};
</script>
<template>
<form #submit.prevent="createSkill">
<form-input-molecule
label="Compétence"
id="name"
name="name"
v-model="skillData.name"
placeholder="Exemple: JavaScript"
:error-message="validationErrors.skillCreationForm?.name"
#input="resetError('name')"
></form-input-molecule>
<form-input-molecule
label="Image"
id="image"
name="image"
type="file"
v-model="skillData.image"
:error-message="validationErrors.skillCreationForm?.image"
#change="previewImage"
#input="resetError('image')"
></form-input-molecule>
<img id="preview-image" width="100" />
<form-input-molecule
label="Progression"
id="progress"
name="progress"
type="number"
v-model="skillData.progress"
placeholder="Exemple: 60"
:min="0"
:max="100"
:error-message="validationErrors.skillCreationForm?.progress"
#input="resetError('progress')"
></form-input-molecule>
<div class="button-wrapper">
<button-atom type="submit" :loading="loading">Créer</button-atom>
</div>
</form>
</template>
I really do not know where these errors are coming from. If you guys could please help me.
If you can put up this code in stackblitz etc with all your dependencies it might be easier for people to help you.
Nevertheless, based on the error messages you have received..regarding the first error...
You have used a v-model for input element which is skillData.image and in the createSkill function you are assigning it a base64 value
skillData.value.image = await toBase64(skillData.value.image);
I think the error is saying that this input field can only have the file name. So maybe you want to look at why you are doing this update. You can just store it in a const.
Regarding the second error, it seems that the Skills route is loading before the values required for that page are received. So maybe you can try to do a v-if in on the skills page to only load on data received. Unable to dig more as you have not shared that page.

Downloading an mp3 file from S3 and manipulating it results in bad file

I did a script that downloads a MP3 file from my S3 bucket and then manipulates in before download (Adding ID3 Tags).
It's working and the tags are injected properly, but the files corrupts as it seems and unplayable.
I still can see my tags trough MP3tag so it has data in it, but no audio is playing trough the file.
Heres my code,
Trying to figure it what went wrong
const downloadFileWithID3 = async (filename, downloadName, injectedEmail) => {
try {
const data = await s3Client.send(
new GetObjectCommand({
Bucket: "BUCKETNAME",
Key: filename,
})
);
const fileStream = streamSaver.createWriteStream(downloadName);
const writer = fileStream.getWriter();
const reader = data.Body.getReader();
const pump = () =>
reader.read().then(({ value, done }) => {
if (done) writer.close();
else {
const arrayBuffer = value;
const writerID3 = new browserId3Writer(arrayBuffer);
const titleAndArtist = downloadName.split("-");
const [artist, title] = titleAndArtist;
writerID3.setFrame("TIT2", title.slice(0, -4));
writerID3.setFrame("TPE1", [artist]);
writerID3.setFrame("TCOM", [injectedEmail]);
writerID3.addTag();
let taggedFile = new Uint8Array(writerID3.arrayBuffer);
writer.write(taggedFile).then(pump);
}
});
await pump()
.then(() => console.log("Closed the stream, Done writing"))
.catch((err) => console.log(err));
} catch (err) {
console.log(err);
}
};
Hope you can help me solve this wierd bug,
Thanks in advance!
Ok so i've figured it out, instead of using chunks of the stream itself i've used getSignedUrl from the s3 bucket it works.
Thanks everyone for trying to help out!

How to get <input tag> from file path Folder Name in ReactJs

I using FileReader and I am trying but I got only getting FileName and FileFormat.
However, I couldn't How to get folderName Soma07
There are several modules available but I don't know how to make it work in React.
Does anybody know?
Here are the examples I found:
const [fileName, setfileName] = useState("")
const upLoadImage = async (e) => {
const file = e.target.files[0]
const base64 = await convertBase64(file);
console.log(base64);
setfileName(file.name)
}
const convertBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = (() => {
resolve(fileReader.result)
})
fileReader.onerror = ((error) => {
reject(error)
})
})
}
Due to security reasons browsers don't allow to get file path. JavaScript in browser has no access to the File System.

Do I have to send files to a server using FormData() in React?

I want to upload an image from the client-side and send it to a server in React. I've searched a bit and found that most tutorials/guides upload the image using a 'file' type input, then append it to a FormData object to send to the server.
Do I need to create the formData object or can I send the same way I would use just text/numbers? Would it work with a regular object like this:
const [selectedFile, setSelectedFile] = useState(null);
const onFileChange = (e: any) => {
setSelectedFile(e.target.files[0]);
console.log(e.target.files[0]);
};
let newTodo = {
title:'New Todo',
description: 'A new task'
todo_pic: selectedFile,
};
Thanks in advance!
it depends on what the backend program expects, base-64 encoded blob or FormData, what you have to do is appending files to formData or pass form event as initial parameter to that, here is a sample code:
function BlahBlah() {
const [image, setImage] = React.useState(undefined);
const handleOnChangeFile = (event) => {
const imgFile = event.target.files[0];
const reader = new FileReader();
reader.addEventListener("loadend", (val) => {
setImage({
file: imgFile,
blob: val.srcElement.result
});
});
reader.readAsDataURL(imgFile);
};
const handleSubmit = () => {
if (image) {
const formData = new FormData();
formData.append("IMAGE", image.file);
console.log("FormData:", formData.get("IMAGE"));
console.log("base-64 encoded blob:", image.blob);
//here you can use XHR/Axios to upload image, e.g:
/*
axios.post("/file-uploader", (formData OR image.blob));
*/
}
};
return (
<div>
<h1>take a look into console!</h1>
<input type="file" onChange={handleOnChangeFile} />
<button disabled={image ? false : true} onClick={handleSubmit}>
Submit!
</button>
</div>
);
}
sandbox link

Trouble using Fetch to grab a JSON value and output as text in html

I am trying to grab a value from an API and output it into my html code as text. The API link is "https://financialmodelingprep.com/api/v3/company/profile/AAPL" (data is in JSON). The code below is my attempt at getting the price. My end goal is to have the user enter a stock ticker into an input box and the price for the stock to be outputted as text. I have successfully used the document.value function for returning values upon button clicks but I am not able to get it to work using an API and fetch.
Thank you very much!
<!DOCTYPE html>
<html>
<head>
<title>Pareto</title>
<script>
function xStockPrice(); {
const fetch = require("node-fetch");
const apiURL = "https://financialmodelingprep.com/api/v3/company/profile/AAPL"
fetch(apiUrl)
.then((res) =>res.json())
.then(data => console.log(data.profile.price))
document.tickerInputForm.output.value=data.profile.price
}
</script>
</head>
<body>
<form name="tickerInputForm">
<input type="text" name="xTicker"/>
<input type="button" value="Get Quote" onclick="xStockPrice();"/>
<input type="text" name="output"/>
</form>
</body>
</html>
You just have a few minor errors in your code, it should look like this:
function xStockPrice(); {
const fetch = require("node-fetch");
const apiURL = "https://financialmodelingprep.com/api/v3/company/profile/AAPL"
// Before you used apiUrl, JavaScript variables are case sensitive
// so apiURL is not the same as apiUrl and vice versa
fetch(apiURL)
.then((res) => res.json())
.then(data => {
console.log(data.profile.price);
// Before this line lived outside of your then handler
// Which causes two issues:
// 1: data will be undefined, it only exists in the scope of this anonymous function
// 2: The code will execute before your request is finished, you use then to wait for the response, so even if you had created the variable data before, it would be undefined when this line was executed, you use then to fill in the value and then you can use it to set the value of your input element
document.tickerInputForm.output.value = data.profile.price;
})
.catch(error => console.log(error));
}
The error in your code is the semi-colon in your function declaration function xStockPrice();
It should be like this:
function xStockPrice(){
const fetch = require("node-fetch");
const apiURL = "https://financialmodelingprep.com/api/v3/company/profile/AAPL"
fetch(apiURL)
.then((res) => res.json())
.then(data => {
console.log(data.profile.price);
document.tickerInputForm.output.value = data.profile.price;
})
.catch(error => console.log(error));
}
Using the JavaScript fetch your code works fine.
<!DOCTYPE html>
<html>
<head>
<title>Pareto</title>
<script>
function xStockPrice() {
// const fetch = require("node-fetch");
const apiURL =
"https://financialmodelingprep.com/api/v3/company/profile/AAPL";
fetch(apiURL)
.then(res => res.json())
.then(data => {
console.log(data.profile.price);
document.tickerInputForm.output.value = data.profile.price;
})
.catch(error => console.log(error));
}
</script>
</head>
<body>
<form name="tickerInputForm">
<input type="text" name="xTicker" />
<input type="button" value="Get Quote" onclick="xStockPrice();" />
<input type="text" name="output" />
</form>
</body>
</html>

Categories

Resources