Developing a File Sharing Platform using Azure ! (PRACTICAL)
Shubham Kumar Gupta
SDE Android @ OLA | Research Intern @ UiT-Norway | 8th Inter IIT Tech Gold | Ex-SDE Team Lead Cueweb | Google Hash Code AIR 19 | GCI'19 Mentor | TechGiG AIR 24 | Bug Hunter | BLE | 16k+ LinkedIn Family ??
Hey! I’m back with another blog, we will be exploring Azure in this medium.
Simran:?Hey! I have heard of Azure, and GCP, a lot but never explored them ??, Can you tell me how to develop something on Azure?
Me:?Yeah, sure once I have developed a file and message sharing platform using Azure, I can explain this.
Simran:?Yeah, this feels interesting can you tell me how to do this and what all we can learn from this?
Me:?We will see how we can create a group, send files/text msgs to Azure container, and how we can fetch and display them. We will also see how to list all conatiners/groups and manage them like deleting of groups and renaming them.
Simran:?Wow! Finally you come with something I wanted to know from long time! Thank You! Can we start?
Me:?Sure, Let’s start! So, first and foremost thing we need is Azure account and education email so that you can get some of the free credits and Azure portal.
Me:?Now let’s move on to this website[Azure for Students — Free Account Credit | Microsoft Azure] where you can fill on your credentials and register at the Azure portal, using this you will get?FREE Credits.
Me:?After registering you can log in to the Azure portal, now this is how our Azure portal looks like
Simran:
Me:?In the Azure portal in this block, we will see how I used?“Function app”, “Resource group”, “App Services”?and?“Storage accounts”?these 4 features from the Azure portal to develop our file or message sharing platform.
10 Steps to Follow:
We will have to follow these 10 steps to make our tasks done
2. We will create a Function App now, just we need to put a function app name and select our resource group, I chose Nodejs version 14, this may depend on one’s need, In hosting tab we need to write our storage app we need and click create new, This will create a Function App and a Storage App
3. We will create a Container inside our Storage App now, just we need to put a container name like here I have used genera, so this can act as public container and anyone can see contents inside this
4. Now We need to create a function inside our Function App, Let’s select HTTPTrigger Function, and paste the below code in the function file
领英推荐
const
Aborter,
BlobURL,
BlockBlobURL,
BlobServiceClient,
ContainerURL,
ServiceURL,
StorageURL,
SharedKeyCredential,
AnonymousCredential,
TokenCredential,
} = require("@azure/storage-blob");
const { saveAs } = require('file-saver');
var multipart = require('parse-multipart');
const AZURE_STORAGE_CONNECTION_STRING = process.env["AZURE_STORAGE_CONNECTION_STRING"];
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
try{
const type = (req.query.type || req.body.type);
const blobServiceClient = await BlobServiceClient.fromConnectionString(AZURE_STORAGE_CONNECTION_STRING);
var list_of_container=[];
for await (const contain of blobServiceClient.listContainers()) {
list_of_container.push(contain.name);
}
async function streamToString(readableStream) {
return new Promise((resolve, reject) => {
const chunks = [];
readableStream.on("data", (data) => {
chunks.push(data.toString());
});
readableStream.on("end", () => {
resolve(chunks.join(""));
});
readableStream.on("error", reject);
});
}
if(type=="download"){
const name = (req.query.name || req.body.name);
const itemname = (req.query.itemname || req.body.itemname);
var container=name?name:"securesharecc";
const containerClient = await blobServiceClient.getContainerClient(container);
const blobName=itemname?itemname:"sample.png";
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const downloadBlockBlobResponse = await blockBlobClient.download(0);
console.log('\nDownloaded blob content...');
var base64String=await streamToString(downloadBlockBlobResponse.readableStreamBody);
console.log('\t', base64String);
context.res = {
body: {data:base64String}
};
context.done();
}
if(type=="create" ){
//name new group name
const name = (req.query.name || req.body.name);
var container=name?name:"securesharecc";
if(!list_of_container.includes(container)){
const newGroupContainerClient = blobServiceClient.getContainerClient(name.toLowerCase());
const createContainerResponse = await newGroupContainerClient.create();
console.log(`Create container ${name} successfully`, createContainerResponse.requestId);
context.res = {
body: {status:200, msg: "created successfully!"}
};
context.done();
}else{
context.res = {
body: {status:500, msg: "Group Already Exists!"}
};
context.done();
}
}
if(type=="delete" ){
const name = (req.query.name || req.body.name);
var container=name?name:"securesharecc";
if(!list_of_container.includes(container)){
context.res = {
body: {status:404, msg: "No such group exists!"}
};
context.done();
}else{
const deleteGroupContainerClient = blobServiceClient.getContainerClient(name.toLowerCase());
const deleteContainerResponse = await deleteGroupContainerClient.delete();
console.log("Container was deleted successfully. requestId: ", deleteContainerResponse.requestId);
context.res = {
body: {status:200, msg: "deleted successfully!"}
};
context.done();
}
}
if(type=="listall" ){
context.res = {
body: {status:200, data: list_of_container }
};
context.done();
}
if(type=="listallcontent" ){
const name = (req.query.name || req.body.name);
console.log('\nListing blobs...');
var container=name?name:"securesharecc";
const containerClient = await blobServiceClient.getContainerClient(container);
var list_content=[];
for await (const blob of containerClient.listBlobsFlat()) {
list_content.push(blob.name);
}
context.res = {
body: {status:200, data: list_content }
};
context.done();
}
function generateRandomNDigits(n){
return Math.floor(Math.random() * (9 * (Math.pow(10, n)))) + (Math.pow(10, n));
}
if(type=="upload" ){
const name = (req.query.name || req.body.name);
var uploadtype = (req.query.uploadtype || req.body.uploadtype);
uploadtype=uploadtype?uploadtype:"text";
var container=name?name:"securesharecc";
const containerClient = await blobServiceClient.getContainerClient(container);
if(uploadtype=="text"){
const msg = (req.query.msg || req.body.msg);
var random=generateRandomNDigits(1)+generateRandomNDigits(3)+generateRandomNDigits(5)+generateRandomNDigits(4)+generateRandomNDigits(7);
random=random.toString();
const blobName = 'text'+random+'.txt';
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const data = msg;
const uploadBlobResponse = await blockBlobClient.upload(data, data.length);
console.log("Blob was uploaded successfully. requestId: ", uploadBlobResponse.requestId);
context.res = {
body: {status:200, msg: "uploaded msg successfully!", value:data, filename:blobName}
};
context.done();
}
if(!list_of_container.includes(container)){
context.res = {
body: {status:404, msg: "No such group exists!"}
};
context.done();
}else{
var bodybuffer = Buffer.from(req.body);
var boundary = multipart.getBoundary(req.headers['content-type']);
var parts = multipart.Parse(bodybuffer, boundary);
const blobName = parts[0].filename;
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobresponse = await blockBlobClient.upload(parts[0].data,parts[0].data.length);
context.res = {
body: {status:200 , msg:"uploaded successfully!" , name: parts[0].filename, type: parts[0].type, data: parts[0].data.length}
};
context.done();
}
//name which container to upload
}
}catch(err){
context.res = {
body: {status: 500, msg:err}
};
context.done();
}
context.res = {
body: {status: 500, msg:"ERR! Try something else!"}
};
context.done();
}
5. Now you need to copy the function URL from the functions app, we will be using this to hit an API and fetch results.
6. Now we need to install some of the npm package so that we can run it smoothly. We need to select our Function App and go in Advanced Tools Section
7. Now from Debug Console we can select CMD, and go inside?“site/wwwroot/HTTPTrigger1”?folder, then we can start with these commands
npm init
npm i @azure/storage-blob
npm i parse-multipart
npm i file-saver
8. Now we need to set an environment variable?“AZURE_STORAGE_CONNECTION_STRING”?which we used in our code, we need to go to our storage account and select “Access Keys”?Section, and select and copy?Key1 connection string
9. We need to paste this key on our Function App inside Configuration
10. Ouff Finally we did this, we need to just make a request to this HTTPTrigger Function and our task is done.
We will create our final local html file to fetch/upload details make sure you replace HTTPTrigger Function URL
<!DOCTYPE html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File sharing Azure</title>
</head>
<body>
<!--
Resource Group: fileshare
storage a/c name: filesharedb
container: general
-->
<!-- UPLOAD SECTION -->
<p>Example of HTTPTRIGGER Function URL is https://myapp.azurewebsites.net/api/HttpTrigger1?code=SAMPLEdfsd/ZT24CSAMPLEbuApg==</p>
<h1>MSG UPLOAD TO AZURE STORAGE BLOB: (CONTAINER: "general" Function: "HttpTrigger1" Type:"Upload" ResourceGrp: "fileshare")</h1>
<form method="post" id="msgform" enctype="multipart/form-data">
<label for="msgtext">Write Text</label>
<input type="text" id="msgtext" name="msgtext"><br><br>
<input type="submit" onclick="return msgUploadFunction();">
</form>
<h1>File UPLOAD TO AZURE STORAGE BLOB: (CONTAINER: "general" Function: "HttpTrigger1" Type:"Upload" ResourceGrp: "fileshare")</h1>
<form method="post" action="YOUR_HTTPTRIGGER_URL&type=upload&name=general&uploadtype=other" enctype="multipart/form-data">
<label for="myfile">Select File</label>
<input type="file" id="myfile" name="filename"><br><br>
<input type="submit">
</form>
<!-- NEW GROUP CREATION SECTION -->
<h1>CREATE A GROUP IN AZURE STORAGE BLOB: (CONTAINER: "write_new_group_name" Function: "HttpTrigger1" Type:"Create" ResourceGrp: "fileshare")</h1>
<form method="post" id="new_group_form" enctype="multipart/form-data">
<label for="new_group_name">Write Name of the Group:</label>
<input type="text" id="new_group_name" name="new_group_name"><br><br>
<input type="submit" onClick="return newGroupCreateFunction();">
</form>
<!-- GROUPA UPLOAD SECTION -->
<h1>GROUPA File UPLOAD TO AZURE STORAGE BLOB: (CONTAINER: "groupa" Function: "HttpTrigger1" Type:"Upload" ResourceGrp: "fileshare")</h1>
<form method="post" action="YOUR_HTTPTRIGGER_URL&type=upload&name=groupa&uploadtype=other" enctype="multipart/form-data">
<label for="myfile">Select File</label>
<input type="file" id="myfile" name="filename"><br><br>
<input type="submit">
</form>
<!-- ANY GROUP UPLOAD SECTION -->
<h1>(ENTER GROUP NAME) File UPLOAD TO AZURE STORAGE BLOB: (CONTAINER: "groupa" Function: "HttpTrigger1" ResourceGrp: "fileshare")</h1>
<form method="post" id="your_group_form" enctype="multipart/form-data">
<label for="your_group_name">Write Name of Your Group:</label>
<input type="text" id="your_group_name" name="your_group_name"><br><br>
<label for="myfile">Select File</label>
<input type="file" id="myfile" name="filename"><br><br>
<input type="submit" onClick="return yourGroupUploadFunction();">
</form>
<!-- LIST ALL GROUPS -->
<h1>LIST ALL CONTAINERS/GROUPS INSIDE AZURE STORAGE BLOB: ( Function: "HttpTrigger1" ResourceGrp: "fileshare")</h1>
<form method="post" id="list_groups_form" action="YOUR_HTTPTRIGGER_URL&type=listall" enctype="multipart/form-data">
<input type="submit" value="Fetch ALL Groups">
</form>
<h1>LIST ALL files in a group INSIDE AZURE STORAGE BLOB: ( Function: "HttpTrigger1" ResourceGrp: "fileshare")</h1>
<form method="post" id="list_group_content_form" enctype="multipart/form-data">
<label for="list_group_content">List Contents of Group(Group Name):</label>
<input type="text" id="list_group_content" name="list_group_content"><br><br>
<input type="submit" value="Fetch ALL Contents of Group" onClick="return listGroupContentFunction();">
</form>
<h1>DOWNLOAD A FILE FROM AZURE STORAGE BLOB: (GROUP NAME: "write_name" (default: "general") Function: "HttpTrigger1" Type:"Upload" ResourceGrp: "fileshare")</h1>
<form method="post" id="download_group_form" enctype="multipart/form-data">
<label for="download_group_name">Write Name of the Group:</label>
<input type="text" id="download_group_name" name="download_group_name"><br><br>
<label for="download_item_name">Write item number of the file to download:</label>
<input type="text" id="download_item_name" name="download_item_name"><br><br>
<input type="submit" onClick="return downloadGroupCreateFunction();">
</form>
<h1>DELETE GROUP ON AZURE STORAGE BLOB: (CONTAINER: "write" Function: "HttpTrigger1" Type:"Upload" ResourceGrp: "fileshare")</h1>
<form method="post" id="delete_group_form" enctype="multipart/form-data">
<label for="delete_group_name">Write Name of the Group:</label>
<input type="text" id="delete_group_name" name="delete_group_name"><br><br>
<input type="submit" onClick="return deleteGroupCreateFunction();">
</form>
<script>
function listGroupContentFunction(){
var action_src = "YOUR_HTTPTRIGGER_URL&type=listallcontent&name="+document.getElementsByName("list_group_content")[0].value;
var msgform = document.getElementById('list_group_content_form');
msgform.action = action_src;
msgform.submit();
}
function msgUploadFunction(){
var action_src = "YOUR_HTTPTRIGGER_URL&type=upload&name=general&uploadtype=text&msg="+document.getElementsByName("msgtext")[0].value;
var msgform = document.getElementById('msgform');
msgform.action = action_src;
msgform.submit();
}
function downloadGroupCreateFunction(){
var action_src = "YOUR_HTTPTRIGGER_URL&type=download&name=" + document.getElementsByName("download_group_name")[0].value+"&itemname="+document.getElementsByName("download_item_name")[0].value;
var download_group_form = document.getElementById('download_group_form');
alert(action_src);
download_group_form.action = action_src;
download_group_form.submit();
}
function deleteGroupCreateFunction(){
var action_src = "YOUR_HTTPTRIGGER_URL&type=delete&name=" + document.getElementsByName("delete_group_name")[0].value;
var delete_group_form = document.getElementById('delete_group_form');
delete_group_form.action = action_src;
delete_group_form.submit();
}
function newGroupCreateFunction(){
var new_group_name=document.getElementById("new_group_name").value;
var action_src = "YOUR_HTTPTRIGGER_URL&type=create&name=" + document.getElementsByName("new_group_name")[0].value;
var new_group_form = document.getElementById('new_group_form');
new_group_form.action = action_src;
new_group_form.submit();
}
function yourGroupUploadFunction(){
var your_group_name=document.getElementById("your_group_name").value;
var action_src = "YOUR_HTTPTRIGGER_URL&type=upload&uploadtype=other&name=" + document.getElementsByName("your_group_name")[0].value;
var your_group_form = document.getElementById('your_group_form');
your_group_form.action = action_src;
your_group_form.submit();
}
</script>
</body>
</html>
This is how our UI looks like with multiple sections
This is how we get responses after a function works properly
Me:?Finally its done! Now one can easily create and manage containers, and how we can upload and fetch files and text messages easily using Azure using our local setup.
Simran:?Good Morning! Are we done? ??
Me:?Sorry this was intensive task and need so much explanation, I skipped much but still I guess you learned how to do this? Hope u enjoyed!
Simran:?Thank You! Finally I can work on Azure now! Thanks a LOT!
Me:?Thank you everyone for reading this article! Do like if you like this! ??