I am trying to upload multiple images to firebase using angular fire.
And using a simple input file. how can I loop for this command to upload multiple images?
I am not using drag and drop, I need to use the input file, and I am using formControl to capture the url.
showPreview(event: any) {
if (event.target.files) {
for (let i = 0; i < event.target.files.length; i++){
const reader = new FileReader();
reader.onload = (event: any) => {
console.log(event.target.result);
this.selectedImage.push(event.target.result);
this.formCadastroAnuncio.patchValue({
fileSource: this.selectedImage
});
}
reader.readAsDataURL(event.target.files[i]);
}
}
else {
this.imgSrc = 'assets/img/image_placeholder.jpg';
}
}
onSubmit(formValue: any) {
this.isSubmitted = true;
const filelist = formValue.target.files;
for (const file of filelist) {
if (this.formCadastroAnuncio.valid) {
let filePath = `${formValue.telefone}/${this.selectedImage}_${new Date().getTime()}`
const fileRef = this.storage.ref(filePath);
this.storage.upload(filePath, this.selectedImage)
.snapshotChanges().pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe((url) => {
formValue['fotos'] = url;
this.service.insertImageDetails(formValue);
})
})
)
.subscribe();
}
}
}
imageDetailsList!: AngularFireList<any>;
constructor(private firebase: AngularFireDatabase) { }
getImageDetailsList(){
this.imageDetailsList = this.firebase.list('imageDetails');
}
insertImageDetails(imageDetails:any) {
this.imageDetailsList.push(imageDetails);
}
Related
i'm using next JS and dropzone to upload an image and send the images to a server. i learned that next JS uses blur hash for static images when used as 'blur' in placeholder. but when it comes to dynamic images fetched from server it needs to be passed the blurhash as well.
so is there a way that i could generate BlurHash myself when i upload images and send them to server? i don't want to use API to generate these hash codes. just pure javascript
dropzone accepted images
const dispatch = useDispatch();
const images = useSelector(selectImages);
const [files, setFiles] = useState(images == [] ? [] : images);
const {getRootProps, getInputProps} = useDropzone({
onDrop: (acceptedFiles) => {
acceptedFiles.map((file, index) => {
const reader = new FileReader();
reader.onload = async function (e) {
const options = {
maxSizeMB: 5,
maxWidthOrHeight: 1920,
useWebWorker: true,
};
const compressedFile = await imageCompression(file, options);
const tot = parseInt(acceptedFiles.length) + parseInt(files.length);
if (tot > 9) {
alert("select maximum of 9 images");
} else if (parseInt(acceptedFiles.length) > 9) {
alert("maximum images to be selected is 9");
} else if (parseInt(files.length) < 9) {
setFiles((prevState) => [
...prevState,
{
id: index,
src: URL.createObjectURL(compressedFile),
name: file.name,
},
]);
files.map((filename) => {
acceptedFiles.forEach((newFile) => {
if (newFile.name == filename.name) {
alert("a duplicate image is detected");
setFiles(
files,
files.filter((val) => val !== newFile)
);
}
});
});
} else {
alert("something went wrong");
}
};
reader.readAsDataURL(file);
return file;
});
},
})
and the output when uploaded
I'm building a simple .gltf plugin for rollup.
The plugin does the following:
Load the .gltf files
Calls emitFile() for any .jpg, .png or .bin dependencies found in the .gltf
Updates the .gltf source with the URLs of the emitted .jpg, .png and .bin
Calls emitFile() for the .gltf itself
The problem is in step 3: emitFile() returns an identifier and there is no way to access the URL using getFileName() until the generation phase has finished. Which means that getFileName() is still not usable in the transform() hook. Besides, I cannot use import.meta.ROLLUP_FILE_URL_${refId} because the file I'm generating is an asset file.
The workaround I've implemented is to patch the .gltf files after the generation but this is not ideal.
What is the proper way to insert emitted file URLs inside assets?
Here's the current code:
import fs from 'node:fs';
import path from 'node:path';
import { createFilter } from '#rollup/pluginutils';
export default function gltf(options = {}) {
const filter = createFilter(options.include, options.exclude);
const exported = [];
return {
name: 'gltf',
load(id) {
if (!id.endsWith('.gltf') || !filter(id)) return null;
const basepath = path.dirname(id);
const source = fs.readFileSync(id);
try {
const model = JSON.parse(source.toString());
const assets = {};
if (model.images) {
model.images.forEach(image => {
const ref = this.emitFile({
type: 'asset',
name: path.basename(image.uri),
source: fs.readFileSync(path.join(basepath, image.uri))
});
assets[image.uri] = ref;
// image.uri = 'import.meta.ROLLUP_FILE_URL_' + ref;
});
}
if (model.buffers) {
model.buffers.forEach(buffer => {
const ref = this.emitFile({
type: 'asset',
name: path.basename(buffer.uri),
source: fs.readFileSync(path.join(basepath, buffer.uri))
});
assets[buffer.uri] = ref;
// buffer.uri = 'import.meta.ROLLUP_FILE_URL_' + ref;
});
}
const ref = this.emitFile({
type: 'asset',
name: path.basename(id),
// source: JSON.stringify(model)
source
});
exported.push({ ref, assets });
return `export default import.meta.ROLLUP_FILE_URL_${ref};`;
} catch (err) {
this.error(err);
}
},
writeBundle(options) {
const done = new Set(); // keep track of the files already patched
exported.forEach(entry => {
const filename = this.getFileName(entry.ref);
if (done.has(filename)) return;
done.add(filename);
const filepath = path.join(options.dir, filename);
const source = fs.readFileSync(filepath);
try {
const model = JSON.parse(source);
if (model.images) {
model.images.forEach(image => {
const ref = entry.assets[image.uri];
if (ref) {
image.uri = path.basename(this.getFileName(ref));
}
});
}
if (model.buffers) {
model.buffers.forEach(buffer => {
const ref = entry.assets[buffer.uri];
if (ref) {
buffer.uri = path.basename(this.getFileName(ref));
}
});
}
fs.writeFileSync(filepath, JSON.stringify(model));
} catch (err) {
this.error(err);
}
});
}
}
}
I have a simple react component where I am using a HTML input (type='file') to upload files. I am using Papa Parse to parse the csv file to JSON. I am doing it with typescript. I have installed both #types/node and #types/papaparse. I would be really great if someone can solve this. I am new to TS.
Please see the below code and attached snapshot of error message I am getting
export const UploadFile: React.FC<{}> = () => {
const fileInputRef = useRef<HTMLInputElement>(null)
const [highlight, setHighlight] = useState<boolean>(false)
const openFileDialog = () => {
if (fileInputRef.current !== null) {
fileInputRef.current.click()
}
}
const onFilesAdded = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = event.target.files
if (files) {
const array = fileListToArray(files)
}
}
const fileListToArray = (list: FileList) => {
const fileList = []
for (let i = 0; i < list.length; i++) {
fileList.push(list.item(i))
if (list !== null && list.item !== null) {
const file = list.item(i)
parse(file, {
complete: (results: object) => {
console.log(results)
}
})
}
}
return fileList
}
You should guard the call with if(file !== null) like so:
export const UploadFile: React.FC<{}> = () => {
const fileInputRef = useRef<HTMLInputElement>(null)
const [highlight, setHighlight] = useState<boolean>(false)
const openFileDialog = () => {
if (fileInputRef.current !== null) {
fileInputRef.current.click()
}
}
const onFilesAdded = (event: React.ChangeEvent<HTMLInputElement>) => {
const files = event.target.files
if (files) {
const array = fileListToArray(files)
}
}
const fileListToArray = (list: FileList) => {
const fileList = []
for (let i = 0; i < list.length; i++) {
fileList.push(list.item(i))
if (list !== null && list.item !== null) {
const file = list.item(i)
if(file !== null) {
parse(file, {
complete: (results: object) => {
console.log(results)
}
}
})
}
}
return fileList
}
This is needed since File Input are sometimes null for one reason or other.
I am trying to post files (Video and Thumbnail) and object to server, but I have an issue because of the structure backend expects. When I do it from postman, this is how it looks like and it works:
{'name': ['Blabla'], 'user': ['8c3a636c-9d08-453d-9e59-7a0ec93200c4'], 'file': [<InMemoryUploadedFile: SampleVideo_1280x720_1mb.mp4 (video/mp4)>]}>
I am having trouble with passing the file like this, don't know how to do it. I tried to do it like this:
videoFile: File[] = [];
thumbnailFile: File[] = [];
files: File[] = [];
readVideoUrl(event:any) {
this.videoFile = [];
const eventObj: MSInputMethodContext = <MSInputMethodContext> event;
const target: HTMLInputElement = <HTMLInputElement> eventObj.target;
const files: FileList = target.files;
if (files) {
this.videoFile.push(files[0]);
this.videoModel.name = files[0].name;
}
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = (event: ProgressEvent) => {
this.videoUrl = (<FileReader>event.target).result;
}
reader.readAsDataURL(event.target.files[0]);
}
}
readThumbUrl(event:any) {
this.thumbnailFile = [];
const eventObj: MSInputMethodContext = <MSInputMethodContext> event;
const target: HTMLInputElement = <HTMLInputElement> eventObj.target;
const files: FileList = target.files;
if (files) {
this.thumbnailFile.push(files[0]);
}
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = (event: ProgressEvent) => {
this.thumbUrl = (<FileReader>event.target).result;
}
reader.readAsDataURL(event.target.files[0]);
}
}
I pass the model and files:
this.campaignService.createVideo(this.videoModel, this.files)
.subscribe(
(response: any) => {
},
(error) => {
console.log(error);
}
);
And here is the issue, how can I create the structure from above with form data, I used to do it like this:
postMultipart(url: string, data: any, files: File[]) {
const formData: FormData = new FormData();
// I understand this stringify is part of the issue,
// just put the code as it is at the moment.
formData.append('data', JSON.stringify(data));
for (const file of files) {
formData.append(file.name, file);
}
const result = this.http.post(url, formData)
.pipe(map((response: Response) => {
return response;
// }
}),
catchError(response => this.handleError(response))
);
return result;
}
But this passes everything like string, and backend is not expecting that. How can I get this (this is just video, the thumbnail is an image):
{'file': [<InMemoryUploadedFile: SampleVideo_1280x720_1mb.mp4 (video/mp4)>]}>
Im using firebase storage, while uploading images to it i also pass in cacheControl pair. Im having trouble on getting the image to cache locally when i download.
Any help pls ..
doupload(event: FileList) {
const file = event.item(0);
if (file.type.split('/')[0] !== 'image') {
console.error('unsupported file type:(');
return;
}
const path = `test/${new Date().getTime()}_${file.name}`;
const fileRef = this.storage.ref(path);
const customMetadata = { app: 'Namma Tiruppur', cacheControl: 'public,max-age=150000', };
this.task = this.storage.upload(path, file, { customMetadata });
this.percentage = this.task.percentageChanges();
this.snapshot = this.task.snapshotChanges().pipe(
tap(snap => {
if (snap.bytesTransferred === snap.totalBytes) {
this.newsImg = path;
}
})
);
this.snapshot.pipe(finalize(() => this.downloadURL = fileRef.getDownloadURL())).subscribe();
}