I am using svelte kit and typescript for my project. I want to be able to save photos that the user sends via the uploadPhoto/+page.svelte I have created:
<script lang="ts">
import { Button } from 'sveltestrap/src';
const dropHandler = (ev: DragEvent) => {
console.log('File(s) dropped');
// Prevent default behavior (Prevent file from being opened)
ev.preventDefault();
if (ev.dataTransfer) {
if (ev.dataTransfer.items) {
// Use DataTransferItemList interface to access the file(s)
[...ev.dataTransfer.items].forEach((item, i) => {
// If dropped items aren't files, reject them
if (item.kind === 'file') {
const file = item.getAsFile();
if (file) {
console.log(`… file[${i}].name = ${file.name}`);
const input = document.getElementById("img") as HTMLInputElement;
input.files = [file];
}
}
});
} else {
// Use DataTransfer interface to access the file(s)
[...ev.dataTransfer.files].forEach((file, i) => {
console.log(` file[${i}].name = ${file.name}`);
const input = document.getElementById("img") as HTMLInputElement;
input.files = [file];
});
}
}
};
const dragOverHandler = (ev: DragEvent) => {
console.log('File(s) in drop zone');
// Prevent default behavior (Prevent file from being opened)
ev.preventDefault();
};
const submitHandler = async (ev: Event) => {
ev.preventDefault();
const formData = new FormData();
const file = (document.getElementById("img") as HTMLInputElement).files![0];
formData.append("img", file);
const response = await fetch("/uploadPhoto?/upload", {
method: "POST",
body: formData
});
const result = await response.json();
console.log(result);
};
</script>
<div class="center-items" style="top:10%;position:absolute">
<h1>Upload Photo</h1>
<br />
<p>Here you can upload a picture of the night sky and identify the stars you have captured.</p>
<p>
After submiting a picture via the drag-and-drop or by selecting a picture, wait for the map to
load in order to see the stars
</p>
<br />
<div id="form" style="top: 15%;width:auto;height:max-content;">
<div id="drop_zone" on:drop={dropHandler} on:dragover={dragOverHandler}>
<label for="img">Select image:</label>
<input type="file" id="img" name="img" accept="image/*" />
<div style="padding-left:80%">
<Button color="primary" on:click={submitHandler}>Submit</Button>
</div>
<p>Drag one file to this <i>drop zone</i>.</p>
</div>
</div>
</div>
<style>
#drop_zone {
border: 5px solid blue;
width: 99%;
height: 40%;
}
@media screen and (max-width: 600px) {
p {
padding-left: 10%;
padding-right: 10%;
text-align: center;
letter-spacing: 0.8px;
}
}
#form {
top: 15%;
width: 90%;
height: max-content;
}
</style>
I know that the form works because I get the file in my uploadPhoto/+page.server.ts:
import { redirect } from '@sveltejs/kit';
import { ImgurClient } from 'imgur';
import type { PageServerLoad, Action, Actions } from './$types';
export const load: PageServerLoad = async ({ locals }) => {
if (!locals.user) {
throw redirect(302, 'login');
}
};
const client = new ImgurClient({
accessToken: process.env.TOKEN,
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN
});
async function uploadToUmgur(file: File) {
const response = await client.upload({
image: file,
type: 'base64'
});
console.log(response.data);
return response.data;
}
const upload: Action = async ({ request }) => {
try
{
if (request.method === 'POST') {
const form = await request.formData();
const image = form.get('img') as File;
console.log(form.get('img'));
if (image) {
console.log(`Received file with name: ${image.name}`);
return await uploadToUmgur(image);
}
}
}catch(e){
console.log(e);
}
};
export const actions: Actions = { upload };
My problem is the following. I want to send the file to the API using the base64 format.
The solution I need is to be able to sort of transform the file variable (in uploadToUmgur function) to base64 format and send it to the API.
I have searched for solutions and all they say is to use FileReader or use fs (the nodejs module for FileSystem) but when I use FileReader I get error that FileReader is not defined. I read that fs actually works with files that are saved in the system. However my idea is just to send the file and not store it in the server’s system.
>Solution :
You can use newer methods for reading the file; to convert to base 64, read it as a buffer and use its toString function:
const buffer = Buffer.from(await file.arrayBuffer());
const base64 = buffer.toString('base64');