Skip to main content

Upload File in Arvancloud Object Storage

With the following code sample, you can receive a file from the user and upload it to the Arvancloud object storage. Just create a bucket in the object storage and run this code using the credentials in the user panel.

The guide to creating a bucket and receiving the access key will help you in this way.

Replace the values ARVANSTORAGE_BUCKET_NAME, ARVANSTORAGE_ACCESS_KEY and ARVANSTORAGE_SECRET_KEY with the name of the bucket, Access Key and Secret Key, respectively.

async function handleRequest(request) {
if (request.method === 'GET') {
// Serve the HTML form when the user accesses the page via a GET request
return new Response(getFormHTML(), {
headers: { 'Content-Type': 'text/html' },
});
} else if (request.method === 'POST') {
// Handle file upload
const contentType = request.headers.get('content-type') || '';

if (contentType.includes('multipart/form-data')) {
const formData = await request.formData();
const file = formData.get('file'); // 'file' is the name of the input field

if (!file) {
return new Response(getResponseHTML('No file found', 'error'), {
headers: { 'Content-Type': 'text/html' },
});
}

const bucket = 'ARVANSTORAGE_BUCKET_NAME';
const s3Key = 'ARVANSTORAGE_ACCESS_KEY';
const s3Secret = 'ARVANSTORAGE_SECRET_KEY';

const fileName = file.name;
const resource = `/${bucket}/${fileName}`;
const dateValue = new Date().toUTCString();

const stringToSign = `PUT\n\n${file.type}\n${dateValue}\n${resource}`;

// Generate HMAC-SHA1 signature using the S3 secret key
const encoder = new TextEncoder();
const keyData = encoder.encode(s3Secret);
const stringData = encoder.encode(stringToSign);

const cryptoKey = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: { name: 'SHA-1' } },
false,
['sign']
);

const signatureBuffer = await crypto.subtle.sign('HMAC', cryptoKey, stringData);
const signature = btoa(String.fromCharCode(...new Uint8Array(signatureBuffer)));

const url = `https://${bucket}.s3.ir-thr-at1.arvanstorage.ir/${fileName}`;
const contentLength = file.size;

// Create the headers
const headers = {
'Host': `${bucket}.s3.ir-thr-at1.arvanstorage.ir`,
'Date': dateValue,
'Content-Type': file.type, // Set the file's content type
'Content-Length': contentLength, // Include the Content-Length header
'Authorization': `AWS ${s3Key}:${signature}`,
};

// PUT request to upload the file
const response = await fetch(url, {
method: 'PUT',
headers: headers,
body: file.stream(), // The file's content stream
});

if (response.ok) {
return new Response(getResponseHTML('File uploaded successfully!', 'success'), {
headers: { 'Content-Type': 'text/html' },
});
} else {
return new Response(getResponseHTML(`File upload failed: ${response.statusText}`, 'error'), {
headers: { 'Content-Type': 'text/html' },
});
}
} else {
return new Response('Unsupported Media Type', { status: 415 });
}
}
}

// Function to return the HTML form as a string
function getFormHTML() {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
}
.container {
max-width: 500px;
margin: 50px auto;
background-color: white;
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1);
border-radius: 10px;
text-align: center;
}
h2 {
text-align: center;
color: #333;
}
.file-input {
display: flex;
flex-direction: column;
margin-bottom: 15px;
}
.file-input label {
font-weight: bold;
margin-bottom: 5px;
color: #555;
}
.file-input input {
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
.submit-btn {
padding: 10px 15px;
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
.submit-btn:hover {
background-color: #218838;
}
</style>
</head>
<body>
<div class="container">
<h2>Upload a File</h2>
<form action="/" method="post" enctype="multipart/form-data">
<div class="file-input">
<label for="file">Choose a file:</label>
<input type="file" name="file" id="file" required>
</div>
<button type="submit" class="submit-btn">Upload</button>
</form>
</div>
</body>
</html>
`;
}

// Function to generate a pleasant response after upload
function getResponseHTML(message, type) {
const color = type === 'success' ? '#28a745' : '#dc3545';
const title = type === 'success' ? 'Success!' : 'Error!';

return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${title}</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
}
.container {
max-width: 500px;
margin: 50px auto;
background-color: white;
padding: 20px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1);
border-radius: 10px;
text-align: center;
}
h2 {
color: ${color};
margin-bottom: 20px;
}
p {
font-size: 18px;
color: #333;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<h2>${title}</h2>
<p>${message}</p>
<a href="/">Upload another file</a>
</div>
</body>
</html>
`;
}

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});