added fixes to upload to handle from client side js for adding files with the new upload spec

This commit is contained in:
2023-05-21 02:21:03 +01:00
parent 53cfee4363
commit 21971dca9e
3 changed files with 290 additions and 48 deletions

1
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/PeernetOfficial/WebGatewayUpload
go 1.18 go 1.18
replace github.com/Akilan1999/p2p-rendering-computation => /Users/akilan/Documents/p2p-rendering-computation replace github.com/Akilan1999/p2p-rendering-computation => /Users/akilan/Documents/p2p-rendering-computation
replace github.com/PeernetOfficial/core => /Users/akilan/Documents/peernet/core
require ( require (
github.com/Akilan1999/p2p-rendering-computation v0.0.0-00010101000000-000000000000 github.com/Akilan1999/p2p-rendering-computation v0.0.0-00010101000000-000000000000

235
main.go
View File

@@ -16,6 +16,7 @@ import (
limiter "github.com/julianshen/gin-limiter" limiter "github.com/julianshen/gin-limiter"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"mime/multipart" "mime/multipart"
"net" "net"
"net/http" "net/http"
@@ -77,7 +78,7 @@ func InitPeernet() *core.Backend {
// RunPeernet Starts the WebAPI and peernet // RunPeernet Starts the WebAPI and peernet
func RunPeernet(backend *core.Backend) { func RunPeernet(backend *core.Backend) {
webapi.Start(backend, []string{*BackEndApiAddress}, false, "", "", 10*time.Second, 10*time.Second, uuid.Nil) webapi.Start(backend, []string{*BackEndApiAddress}, false, "", "", 200000*time.Second, 200000*time.Second, uuid.Nil)
backend.Connect() backend.Connect()
for { for {
@@ -133,41 +134,162 @@ type BlockchainResponse struct {
// ---------------------------------- Warehouse related ------------------------------------ // ---------------------------------- Warehouse related ------------------------------------
// AddFileWarehouse API call for (Storing file in the warehouse) // AddFileWarehouse API call for (Storing file in the warehouse)
func AddFileWarehouse(file io.Reader) *WarehouseResult { //func AddFileWarehouse(file io.Reader, id string) *WarehouseResult {
// route := BackendAddressWithHTTP + "/warehouse/create"
//
// form := url.Values{}
// form.Add("file", file)
// form.Add("ip", c.ip)
// form.Add("ua", c.ua)
// req.PostForm = form
//
// req, err := http.NewRequest("POST", route, file)
// //req.Header.Set("X-Custom-Header", "myvalue")
// req.Header.Set("Content-Type", "multipart/form-data")
//
// client := &http.Client{}
// resp, err := client.Do(req)
// if err != nil {
// panic(err)
// }
// defer resp.Body.Close()
//
// body, err := ioutil.ReadAll(resp.Body)
// if err != nil {
// fmt.Println(err)
// }
// var result WarehouseResult
// err = json.Unmarshal(body, &result)
// if err != nil {
// fmt.Println(err)
// }
//
// return &result
//}
func AddFileWarehouse(File io.Reader, uuid string) (resp *WarehouseResult, err error) {
//// Prepare a form that you will submit to that URL.
//var b bytes.Buffer
//w := multipart.NewWriter(&b)
//for key, r := range values {
// var fw io.Writer
// if x, ok := r.(io.Closer); ok {
// defer x.Close()
// }
// // Add an image file
// if x, ok := r.(*os.File); ok {
// if fw, err = w.CreateFormFile(key, x.Name()); err != nil {
// return
// }
// } else {
// // Add other fields
// if fw, err = w.CreateFormField(key); err != nil {
// return
// }
// }
// if _, err = io.Copy(fw, r); err != nil {
// return nil, err
// }
//
//}
//// Don't forget to close the multipart writer.
//// If you don't close it, your request will be missing the terminating boundary.
//w.Close()
//
//// Now that you have a form, you can submit it to your handler.
//req, err := http.NewRequest("POST", BackendAddressWithHTTP+"/warehouse/create", &b)
//if err != nil {
// return
//}
//// Don't forget to set the content type, this will contain the boundary.
//req.Header.Set("Content-Type", w.FormDataContentType())
//
//client := &http.Client{}
//
//// Submit the request
//res, err := client.Do(req)
//if err != nil {
// return
//}
//
//// Check the response
//if res.StatusCode != http.StatusOK {
// err = fmt.Errorf("bad status: %s", res.Status)
//}
//
//body, err := ioutil.ReadAll(res.Body)
//if err != nil {
// return
//}
//
//err = json.Unmarshal(body, &resp)
//if err != nil {
// return
//}
//
//fmt.Println(resp)
//
//return
url := BackendAddressWithHTTP + "/warehouse/create" url := BackendAddressWithHTTP + "/warehouse/create"
req, err := http.NewRequest("POST", url, file) method := "POST"
//req.Header.Set("X-Custom-Header", "myvalue")
req.Header.Set("Content-Type", "multipart/form-data") payload := &bytes.Buffer{}
writer := multipart.NewWriter(payload)
_ = writer.WriteField("id", uuid)
part2, errFile2 := writer.CreateFormFile("File", "test")
_, errFile2 = io.Copy(part2, File)
if errFile2 != nil {
fmt.Println(errFile2)
return
}
err = writer.Close()
if err != nil {
fmt.Println(err)
return
}
client := &http.Client{} client := &http.Client{}
resp, err := client.Do(req) req, err := http.NewRequest(method, url, payload)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return
} }
var result WarehouseResult req.Header.Set("Content-Type", writer.FormDataContentType())
err = json.Unmarshal(body, &result) res, err := client.Do(req)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
} }
return &result err = json.Unmarshal(body, &resp)
if err != nil {
return
}
return
} }
// UploadFile Simple abstracted function to add files to peernet core // UploadFile Simple abstracted function to add files to peernet core
func UploadFile(backend *core.Backend, file *multipart.File, header *multipart.FileHeader) (*btcec.PublicKey, *WarehouseResult, error) { func UploadFile(backend *core.Backend, file *multipart.File, header *multipart.FileHeader, uuid string) (*btcec.PublicKey, *WarehouseResult, error) {
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
if _, err := io.Copy(buf, *file); err != nil { if _, err := io.Copy(buf, *file); err != nil {
return nil, nil, errors.New("io.Copy not successful") return nil, nil, errors.New("io.Copy not successful")
} }
// adds file to warehouse // adds file to warehouse
warehouseResult := AddFileWarehouse(buf) warehouseResult, err := AddFileWarehouse(buf, uuid)
if err != nil {
fmt.Println(err.Error())
return nil, nil, err
}
// current using default port for Peernet api which is 8080 // current using default port for Peernet api which is 8080
// First add file to warehouse // First add file to warehouse
@@ -225,9 +347,37 @@ func AddFileToBlockchain(hash []byte, filename string) *BlockchainResponse {
return nil return nil
} }
fmt.Println(result)
return &result return &result
} }
// ---------------------------------------------------------------------------------------------
// ----------------------------------- Get status upload file ---------------------------------
func GetStatusUploadFile(uuid string) (uploadStatus *webapi.UploadStatus) {
url := BackendAddressWithHTTP + "/create/track/uploadID?id=" + uuid
resp, err := http.Get(url)
if err != nil {
log.Fatalln(err)
}
//We Read the response body on the line below.
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
err = json.Unmarshal(body, uploadStatus)
if err != nil {
return nil
}
fmt.Println(uploadStatus.Progress.Percentage)
return
}
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
@@ -251,6 +401,8 @@ func main() {
r = gin.Default() r = gin.Default()
} }
r.Use(CORSMiddleware())
r.LoadHTMLGlob("templates/*.html") r.LoadHTMLGlob("templates/*.html")
r.Static("/templates", "./templates") r.Static("/templates", "./templates")
@@ -262,8 +414,8 @@ func main() {
// ---------------------------------------- Routes --------------------------------------------- // ---------------------------------------- Routes ---------------------------------------------
// GET /upload to open upload page from webgateway // GET /upload to open upload page from webgateway
r.GET("/upload", lm.Middleware(), func(c *gin.Context) { r.GET("/", lm.Middleware(), func(c *gin.Context) {
c.HTML(http.StatusOK, "upload.html", nil) c.HTML(http.StatusOK, "upload.html", gin.H{"backendUrl": *BackEndApiAddress})
}) })
// POST /uploadFile Uploads file to peernet from Webgateway // POST /uploadFile Uploads file to peernet from Webgateway
@@ -271,6 +423,8 @@ func main() {
file, header, err := c.Request.FormFile("file") file, header, err := c.Request.FormFile("file")
defer file.Close() defer file.Close()
uuid := c.Request.FormValue("uuid")
if err != nil { if err != nil {
c.HTML(http.StatusBadRequest, "upload.html", gin.H{ c.HTML(http.StatusBadRequest, "upload.html", gin.H{
"error": err, "error": err,
@@ -278,25 +432,34 @@ func main() {
return return
} }
publicKey, warehouseResult, err := UploadFile(backend, &file, header) publicKey, warehouseResult, err := UploadFile(backend, &file, header, uuid)
if err != nil { if err != nil {
c.HTML(http.StatusBadRequest, "upload.html", gin.H{ c.HTML(http.StatusBadRequest, "upload.html", gin.H{
"error": err, "backendUrl": *BackEndApiAddress,
"error": err,
}) })
return return
//fmt.Println(err) //fmt.Println(err)
} }
c.HTML(http.StatusOK, "upload.html", gin.H{ c.JSON(http.StatusOK, gin.H{
"hash": hex.EncodeToString(warehouseResult.Hash), "hash": hex.EncodeToString(warehouseResult.Hash),
"filename": header.Filename, "filename": header.Filename,
"size": header.Size, "size": header.Size,
"link": "http://164.90.177.167:8889/" + hex.EncodeToString(publicKey.SerializeCompressed()) + "/" + hex.EncodeToString(warehouseResult.Hash) + "/?filename=" + header.Filename, "link": "http://164.90.177.167:8889/" + hex.EncodeToString(publicKey.SerializeCompressed()) + "/" + hex.EncodeToString(warehouseResult.Hash) + "/?filename=" + header.Filename,
"address": *WebpageAddress, "address": *WebpageAddress,
"backendUrl": *BackEndApiAddress,
}) })
}) })
r.GET("/uploadStatus", lm.Middleware(), func(c *gin.Context) {
uuid := c.Query("uuid")
c.JSON(http.StatusOK, GetStatusUploadFile(uuid))
})
// Implement CURL script to ensure linux users can upload directly // Implement CURL script to ensure linux users can upload directly
// the Cli like https://bashupload.com // the Cli like https://bashupload.com
// Ex: curl http://localhost:8080/uploadCurl -F add=@<file name> // Ex: curl http://localhost:8080/uploadCurl -F add=@<file name>
@@ -308,7 +471,7 @@ func main() {
fmt.Println(err) fmt.Println(err)
} }
publicKey, warehouseResult, err := UploadFile(backend, &file, header) publicKey, warehouseResult, err := UploadFile(backend, &file, header, "")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
@@ -365,3 +528,21 @@ func EscapeNATWebGateway() (ExposePortP2PRC string, err error) {
return return
} }
// CORSMiddleware Use Cors middleware
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Credentials", "true")
c.Header("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Header("Access-Control-Allow-Methods", "POST,HEAD,PATCH, OPTIONS, GET, PUT")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}

View File

@@ -14,6 +14,19 @@
</head> </head>
<style>
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 1%;
height: 30px;
background-color: #04AA6D;
}
</style>
<body> <body>
<section class="ftco-section"> <section class="ftco-section">
<div class="container"> <div class="container">
@@ -25,16 +38,20 @@
<h2 class="Peernetblue">Upload file to peernet</h2> <h2 class="Peernetblue">Upload file to peernet</h2>
<br> <br>
<br> <br>
<form class="form-group" method="POST" action="/upload" enctype="multipart/form-data"> <!-- <form class="form-group" method="POST" action="/upload" enctype="multipart/form-data">-->
<div class="form-group mb-3"> <div class="form-group mb-3">
<!-- <label for="formFileLg" class="form-label">Upload your file</label> --> <!-- <label for="formFileLg" class="form-label">Upload your file</label> -->
<input class="btn btn-white btn-outline-white" id="formFileLg" type="file" name="file" required> <input class="btn btn-white btn-outline-white" id="formFileLg" type="file" name="file" required>
</div> </div>
<input class="btn btn-white btn-outline-white" type="submit" value="Submit"> <input class="btn btn-white btn-outline-white" type="button" value="Submit" onclick="uploader()">
{{ if .error }} {{ if .error }}
<h3 style="color:red"> Error: {{ .error }} </h3> <h3 style="color:red"> Error: {{ .error }} </h3>
{{end}} {{end}}
</form> <!-- </form>-->
<!-- <div id="myProgress">-->
<!-- <div id="myBar"></div>-->
<!-- </div>-->
<br> <br>
<!-- <div class="progress">--> <!-- <div class="progress">-->
<!-- <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 3%"></div>--> <!-- <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 3%"></div>-->
@@ -63,15 +80,11 @@
<form action="#" class="signin-form"> <form action="#" class="signin-form">
<div class="form-group mb-3"> <div class="form-group mb-3">
<label class="label" for="name">File Name:</label> <label class="label" for="name">File Name:</label>
{{ if .filename }} <p id="fileName"> {{ .filename }} </p>
<p> {{ .filename }} </p>
{{end}}
</div> </div>
<div class="form-group mb-3"> <div class="form-group mb-3">
<label class="label" for="name">File Size:</label> <label class="label" for="name">File Size:</label>
{{ if .size }} <p id="fileSize"> {{ .size }} bytes</p>
<p> {{ .size }} bytes</p>
{{end}}
</div> </div>
<!-- <div class="form-group mb-3">--> <!-- <div class="form-group mb-3">-->
<!-- <label class="label" for="name">File Hash:</label>--> <!-- <label class="label" for="name">File Hash:</label>-->
@@ -82,9 +95,7 @@
<div class="form-group mb-3"> <div class="form-group mb-3">
<label class="label" for="name">Sharable Link:</label> <label class="label" for="name">Sharable Link:</label>
<br> <br>
{{ if .link }} <a href="{{ .link }}" style="color:#1d91ac" target="_blank" id="fileLink"></a>
<a href="{{ .link }}" style="color:#1d91ac" target="_blank">{{ .filename }} link</a>
{{end}}
</div> </div>
<!-- <div class="form-group mb-3"> <!-- <div class="form-group mb-3">
<label class="label" for="password">Password</label> <label class="label" for="password">Password</label>
@@ -124,15 +135,64 @@
// The second call will start the upload based // The second call will start the upload based
// on the ID presented // on the ID presented
// //
// function uploader() {
// var formData = new FormData(); var backendUrl = {{ .backendUrl }}
// formData.append("name", "Smith"); function uploader() {
// formData.append("data", fileInputElement.files[0]); var formData = new FormData();
// var request = new XMLHttpRequest(); var uuid = generateUUID()
// formData.append("id", uuid);
// request.open("POST", "https://site[DOT]net/upload"); formData.append("file", document.getElementById("formFileLg").files[0]);
// request.send(formData); var request = new XMLHttpRequest();
// }
request.open("POST", "/upload");
request.send(formData);
//
// setTimeout(function(){
// console.log(UploadTracker(uuid));
// }, 100);
request.onload = () => {
if ( request.readyState == 4 && request.status == 200) {
let data = request.response;
console.log(data);
data = JSON.parse(data)
document.getElementById("fileName").innerText = data["filename"]
document.getElementById("fileSize").innerText = data["size"] + " bytes"
document.getElementById("fileLink").innerText = data["filename"] + " link"
document.getElementById("fileLink").href = data["link"]
} else {
console.log(`Error: ${ request.status}`);
}
};
}
function UploadTracker(uuid) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", "/uploadStatus?uuid=" + uuid, false ); // false for synchronous request
xmlHttp.send( null );
return xmlHttp.responseText;
}
// source: https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid
function generateUUID() { // Public Domain/MIT
var d = new Date().getTime();//Timestamp
var d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now()*1000)) || 0;//Time in microseconds since page-load or 0 if unsupported
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16;//random number between 0 and 16
if(d > 0){//Use timestamp until depleted
r = (d + r)%16 | 0;
d = Math.floor(d/16);
} else {//Use microseconds since page-load if supported
r = (d2 + r)%16 | 0;
d2 = Math.floor(d2/16);
}
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
</script> </script>