I am trying to stream a mp4 file that is on my computer. I am able to upload and delete the files. When the upload completes and click the link. it routes me to the page and I only see {}. and I get the following errors:
GET http://localhost:8000/read/c94e2bfe215bb8821c5c8dc22c8dc1b4.mp4 400 (Bad Request)
favicon.ico:1 GET http://localhost:8000/favicon.ico 404 (Not Found)
I even uploaded a picture to see to check if the mp4 file was too big, but the picture did not load as well.
Here is my code for my server:
// route for streaming a file
app.get('/read/:filename',async(req,res)=>{
const{filename}= req.params
try{
const readstream = await gfs.createReadStream({filename})
res.header("Content-Type","video/mp4");
res.header("X-Content-Type-Options", "nosniff");
res.header("Accept-Ranges", "bytes");
res.header("Content-Length",903746);
readstream.pipe(res)
}catch(err){
res.status(400).send(err)
}
})
Here is the code for react
function App() {
const [file, setFile] = React.useState(null);
const [files, setFiles] = React.useState([]);
const filehandler = (e) => {
if (e.target.files != null || e.target.files[0] != null) {
setFile(e.target.files[0]);
}
};
const uploadFile = async (e) => {
e.preventDefault();
if (file) {
const fd = new FormData();
fd.append("file", file);
const res = await axios.post("http://localhost:8000/upload", fd);
setFiles(files.concat(res.data))
}
};
const fetchFiles = React.useCallback(async () => {
const res = await axios.get("http://localhost:8000/files");
setFiles(res.data);
}, []);
const removeFile = React.useCallback(
async (filename, index) => {
const res = await axios.delete(
`http://localhost:8000/delete/${filename}`
);
if (res.status === 200) {
let temp = [...files];
console.log(temp);
temp.splice(index, 1);
setFiles(temp);
}
},
[files]
);
React.useEffect(() => {
fetchFiles();
}, [fetchFiles]);
return (
<div className="App">
<form className="Form" onSubmit={uploadFile}>
<input type="file" onChange={filehandler} />
<button type="submit">upload</button>
</form>
<div className="Media">
{files.map((file, i) => (
<div key={file._id} className="Item">
<a
className="Link"
href={`http://localhost:8000/read/${file.filename}`}
>
{file.filename}
</a>
<button
type="button"
onClick={() => {
removeFile(file.filename, i);
}}
>
remove
</button>
</div>
))}
</div>
</div>
);}
Your router is sending 400 after catching an exception. Print exception message using console.log(err) in your catch block to determine what exactly goes wrong it try block's code
Related
I made function that upload multiple images to storage and save links to document but i can't figure out how to monitor progress.
const getURLS = async () => {
const promises = [];
images &&
images.map((image) => {
const storageRef = ref(storage, `images/${image?.file?.name + v4()}`);
promises.push(
uploadBytesResumable(storageRef, dataURLtoBlob(image.data_url)).then((uploadResult) => {
return getDownloadURL(uploadResult.ref);
})
);
});
const urls = await Promise.all(promises);
try {
await addDoc(collection(db, 'posts'), {
message: data,
createdAt: serverTimestamp(),
createdBy: user,
likes: [],
comments: [],
images: urls,
}).then(() => {
setData('');
setImages([]);
});
} catch (err) {
console.log(err);
}
};
How to add firebase monitor upload progress to this function?
I tried different ways but it dosn't work
thx for help
The uploadBytesResumable() does not return a promise but an UploadTask. You can iterate over all the images selected and track their progress individually as shown below:
function App() {
const [images, setImages] = useState([])
const [progress, setProgress] = useState([])
const handleFileChange = (e) => {
const files = e.target.files
const newImages = []
for (let i = 0; i < files.length; i++) {
newImages.push(files[i])
}
setImages(newImages)
}
const handleUpload = async () => {
for (let i = 0; i < images.length; i++) {
const image = images[i]
const storageRef = ref(storage, `images/${image.name}`)
const uploadTask = uploadBytesResumable(storageRef, image)
uploadTask.on('state_changed', (snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
setProgress((prevProgress) => {
const newProgress = [...prevProgress]
newProgress[i] = progress.toFixed(2)
return newProgress
})
}, (error) => {
console.log(error)
}, async () => {
const imageUrl = await getDownloadURL(uploadTask.snapshot.ref)
// Add to Firestore
})
}
}
return (
<div className="App">
<input type="file" multiple onChange={handleFileChange} />
<button onClick={handleUpload}>Upload</button>
{progress.map((progress, i) => (
<div key={i}>{images[i].name} {progress}%</div>
))}
</div>
)
}
Each file is uploaded separately so you would have to implement some logic to get all URLs together and add in Firestore document like you can call a function when progress of all uploads i.e. all items in progress array become 100.
I am trying to display an image on a profile of a user. I have been able to fetch the blob from the API and convert it to a URL blob but when I am trying to return it from the function and into the SRC of the tag, nothing is being displayed.
Previously I was simply displaying the image with <src = ""> and the src that I have put in the function, but when I implemented authentication, this no longer worked because there was a 401 unauthenticated error since no bearer token was sent with the request.
Output:
//profile.js
export const Profile = () => {
const [userProfileInformation, setUserProfileInformation] = useState([]);
const [isLoading, setLoading] = useState(true);
const { userId } = useParams();
useEffect(() => {
getUserProfileInformation().then(() => {
setLoading(false);
});
}, []);
const getUserProfileInformation = async () => {
const response = await UserService.getUserProfileInformation(userId)
.then(response => response.json())
.then(data => {
setUserProfileInformation(data);
});
}
const getProfileImage = async () => {
const src = config.URL + "/users/" + userProfileInformation.userId + "/image/download";
const options = {
headers: {
"Authorization" : `Bearer
${AuthService.getCurrentlyAuthenticatedUser().accessToken}`,
}
};
fetch(src, options)
.then(res => res.blob())
.then(blob => {
console.log(blob);
let url = URL.createObjectURL(blob);
console.log(url);
return url;
});
}
if (isLoading) {
return (
<div id="loading">
<h2>Loading...</h2>
</div>
)
}
return (
<div>
<AppNavbar />
<div className="profileCard">
<img id="profileImg" src={getProfileImage()}/>
<h1>{getFullName(userProfileInformation.firstName, userProfileInformation.lastName)}</h1>
<h2 id="email" role="email">{userProfileInformation.email}</h2>
<h2>{userProfileInformation.location}</h2>
)
}
Any help would be appreciated, thanks.
I have this code from firebase documentation on my firebase file
export async function deleteImage(docId){
// Create a reference to the file to delete
const desertRef = ref(storage, `images/${docId}`);
await deleteObject(desertRef).then(() => {
swal("GOOD", "success");
}).catch((error) => {
swal("error!", "error");});
}
➡️ And i have this code for upload and download URL image on my Dashboard View
async function handleOnChangeProfileImage(e) {
console.log(e.target);
setLoading(true) // Setloading to true
var fileList = e.target.files;
var fileReader = new FileReader();
if (fileReader && fileList && fileList.length > 0) {
fileReader.readAsArrayBuffer(fileList[0]);
fileReader.onload = async function () {
var imageData = fileReader.result;
const res = await setUserProfilePhoto(currentUser.uid, imageData);
if (res) {
const tmpUser = { ...currentUser };
tmpUser.profilePicture = res.metadata.fullPath;
setCurrentUser({ ...tmpUser });
await updateUser(tmpUser);
const url = await getProfilePhotoUrl(currentUser.profilePicture);
setProfileUrl(url);
//updateUserProfilePhoto(currentUser.uid, res.fullPath);
}
};
}
}
➡️ And this is in html
<img className="mb-3 lazyload" key={profileUrl} srcSet={profileUrl} data-src={userImg}
width={200} alt="web.app" />
<Button onClick={handleOpenFilePicker} variant="primary"><FontAwesomeIcon icon={faUpload} /> Upload</Button>
<Button onClick={deleteImage} variant="danger"><FontAwesomeIcon icon={faDeleteLeft}/> Delete</Button>
I can upload an image successfully, but i want to delete the user's profile image with a OnClick event, and for that I use his docId as a reference, but the result is negative, what else do I have to create or do to delete the uploaded image? Hope you help me!! Thanks a lot!
I have a problem with saving pictures in the database. I want to do a post Method, where i can safe a file in a directory and save the picture link in the database.
Here is my Code:
`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 [base64Image, setBase64Image] = useState("")
const [imagePath, setImagePath] = useState("")
const fileInput = useRef(null)`
`const onFileInputChange = async (e) => {
const file = fileInput.current.files[0]
if (!file) return
const base64 = await toBase64(file)
setBase64Image(base64)}`
` const handleSubmitImage = async (e) => {
e.preventDefault()
if (!base64Image) return
const response = await fetch("/public", {
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(base64Image)
})
const data = await response.json()
setImagePath(data.filePath)
}`
Post:
`const handleSubmit = async (e) => {
e.preventDefault()
setIsLoading(true)
setErrors(defaultModel)
const result = validateModel(post)
if (!result.isValid) {
setErrors(result.errors)
setIsLoading(false)
return
}
if (post.id) {
await updatePost(post, session.accessToken)
alert("Post updated!")
router.push(`/posts/${post.id}`)
} else {
const newPost = await createPost(post, session.accessToken)
alert("Post created!")
router.push(`/posts/${newPost.id}`)
}
setIsLoading(false)
}
`
` <fieldset onSubmit={handleSubmitImage} className={styles.form}>
<p>Image:</p>
<input value={post.image}
type="file"
accept=".png,.jpg"
ref={fileInput}
onChange={onFileInputChange}
/>
{/* eslint-disable-next-line #next/next/no-img-element */}
{base64Image && <img src={base64Image} style={{width: "1000px", height: "1000px"}} alt={""}/>}
{imagePath && <p>
<Link href={`http://localhost:3000${imagePath}`}
passHref><a>http://localhost:3000{imagePath}</a></Link>
</p>
}
</fieldset>`
Right now i can connect to the Explorer and pick an Image. I can also display the image. If i press on create, it doesnt work properly with saving the image in the database.
When I request api, I want to make conditional according to the answer, but it doesn't assign the value I want to errorMessageUploaded. Do you have an idea?
I want to get a message when the error comes from api, but when the response comes errormessageupload variable without ending the request.
Not working conditional.
let uploadLoading = false;
let errorMessageUploaded = null;
`function Previews(props) {
const [files, setFiles] = useState([]);
const [test, testFile] = useState(null);
const { getRootProps, getInputProps } = useDropzone({
noClick: props.uploadDisable,
accept: "application/vnd.ms-excel,
application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet",
onDrop: acceptedFiles => {
uploadLoading = true;
var file = acceptedFiles[0];
fileName = file.path;
const reader = new FileReader();
let data = {
file: null,
purchase_order_id: props.purchaseorderid
};
reader.onload = event => {
uploadLoading = true;
data.file = event.target.result.replace(
"data:application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet;base64,",
""
);
});
(async () =>
await axios
.post(
baseUrl + "v1/purchaseorder/uploadpurchaseorder",
data,
axiosConfig
)
.then(response => {
uploadLoading = false;
errorMessageUploaded = null;
window.location.reload();
})
.catch(error => {
errorMessageUploaded = "test";
uploadLoading = false;
throw error;
}))();
reader.readAsDataURL(file);
}
});
const thumbs = files.map(file => (
<FontAwesomeIcon icon={faFileExcel}
className="excelUploadThumbs" />
));
useEffect(
() => () => {
// Make sure to revoke the data uris to avoid memory leaks
files.forEach(file => URL.revokeObjectURL(file.preview));
},
[files]
);
return uploadLoading == false ? (
<section className="container">
<div {...getRootProps({ className: "dropzone" })}>
<input {...getInputProps()} />
<p className="dropzoneText1">Drop your file here</p>
<p className="dropzoneText2">or</p>
<p className="dropzoneText3">Select file</p>
</div>
<aside style={thumbsContainer}>{thumbs}</aside>
</section>
) : errorMessageUploaded != null ? (
<section className="container">
<div className="displayErrorDiv">
<p className="serviceError"> {errorMessageUploaded} </p>
</div>
</section>
) : (
<section className="container">
Data is uploading...
<aside style={thumbsContainer}>{thumbs}</aside>
</section>
);
}`
Code unclear but these may be helpful.
use uploadLoading & errorMessageUploaded with useState
need cancelToken
let source = Axios.CancelToken.source();
const Send = async (url, method, data) => {
try {
source && source.cancel("Operation canceled due to new request.");
source = Axios.CancelToken.source();
return await Axios({ method, url, data, cancelToken: source.token });
} catch (error) {
if (Axios.isCancel(error)) {
return Promise.resolve("canceled");
} else {
return Promise.reject(error);
}
}
};