Minio: how to get right link to display image on html - html

I need to get images from Minio bucket, but I cannot display that image.
I found out that problem was in link. I cannot open it even with browser. So, here is the problem:
GET https://127.0.0.1:9000/myphotos/Jungles.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=7PAB237ARMGX7RTYHUSL%2F20221202%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20221202T133028Z&X-Amz-Expires=604800&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiI3UEFCMjM3QVJNR1g3UlRZSFVTTCIsImV4cCI6MTY3MDAyNzIyNiwicGFyZW50IjoiS2VtYWxBdGRheWV3In0.okb2wO_iLhOlwWeNbixec4R5MRgGw2_KCY_SB9NfuseUI3g9gzTccycbaA6UnZiuuLzbpxPM5tR_hnxa_Y8zWQ&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=281fab24bbe3d651f89c160f5a613512f5e4503f40300ef0008ac94bd9c8f90b
net::ERR_CONNECTION_REFUSED
My code that has been used to upload that file:
package main
import (
"context"
"log"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
)
func main() {
ctx := context.Background()
endpoint := "play.minio.io"
accessKeyId := "KemalAtdayew"
secretAccessKey := "K862008971a!"
useSSL := true
// init minio client object
minioClient, err := minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKeyId, secretAccessKey, ""),
Secure: useSSL,
})
if err != nil {
log.Fatalln(err)
}
// make a new bucket called myphoto
bucketName := "photobucket"
location := "us-east-1"
err = minioClient.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{Region: location})
if err != nil {
// check to see if we already own this bucket
exists, errBucketExists := minioClient.BucketExists(ctx, bucketName)
if errBucketExists == nil && exists {
log.Printf("We already own %s\n", bucketName)
} else {
log.Fatalln(err)
}
} else {
log.Printf("Successfully created %s\n", bucketName)
}
// upload you photos
objectName := "Jungles.jpeg"
filePath := "/minio-1/Jungles.jpeg"
contentType := "image/jpeg"
// upload the zip file FPutObject
info, err := minioClient.FPutObject(ctx, bucketName, objectName, filePath, minio.PutObjectOptions{ContentType: contentType})
if err != nil {
log.Fatalln(err)
}
log.Printf("Successfully uploaded %s of size %d\n", objectName, info.Size)
}
I also gave permission and made it public. Still nothing.
<!DOCTYPE html>
<html>
<head>
<title> Minio </title>
<meta charset="utf-8">
</head>
<body>
<div>
<img src="https://127.0.0.1:9000/myphotos/Jungles.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=7PAB237ARMGX7RTYHUSL%2F20221202%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20221202T124101Z&X-Amz-Expires=604800&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiI3UEFCMjM3QVJNR1g3UlRZSFVTTCIsImV4cCI6MTY3MDAyNzIyNiwicGFyZW50IjoiS2VtYWxBdGRheWV3In0.okb2wO_iLhOlwWeNbixec4R5MRgGw2_KCY_SB9NfuseUI3g9gzTccycbaA6UnZiuuLzbpxPM5tR_hnxa_Y8zWQ&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=5027bd8021a58548ce6be5dead3b622afd951f157a289320ef7dab7701baa7d2" alt="Photo from Minio">
</div>
</body>
</html>
Tried to change html code. Then, found out that it's not html problem.
Tried to share in any other possible way except than, "bucket->click on photo -> click on share"
Link is invalid, but there is no other proper way to get link to that image in bucket.

The path to your local image seems to be strange. Verify if you can open your image manually, and remove all the parameters after the image extension, it should be Forest.jpg

The path to your local image seems to be strange. Verify if you can open your image manually, and remove all the parameters after the image extension, it should be Forest.jpg

If you have Minio running in a container, it is always a mess with 127.0.0.1 or localhost.
Try to generate the link with the minioclient.
mc alias set myminio http://localhost:9000 user password
mc share download myminio/mybucket/object.txt
it will return something like this:
mc share download --recursive minio/testbucket
URL: http://localhost:9000/testbucket/KUBERNETES_AN_ENTERPRISE_GUIDE.pdf
Expire: 7 days 0 hours 0 minutes 0 seconds
Share: http://localhost:9000/testbucket/KUBERNETES_AN_ENTERPRISE_GUIDE.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20221207%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20221207T130336Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=8668da57727f04e7c7e8b15f5d8852fa3801e323cfbc6198384737b77f54cb0b
That link you can open in your Browser.
Note --recursive generate links for all the uploaded files in the bucket.
To get one specific use:
mc share download myminio/testbucket/object.txt.
In production mode as you will use full qualified domain names and not 127.0.0.1 or localhost.
Take a look here about the mc command for generating the link.
https://min.io/docs/minio/linux/reference/minio-mc/mc-share-download.html
If you have a backend and according to your programming language you can also generate links through the api.
Here you find a example for javascript:
https://min.io/docs/minio/linux/developers/javascript/API.html#presignedUrl

Related

What causes browsers to open "Save As" window when downloading dynamic content?

I am experimenting with an idea to stream dynamic data from a web server into a file on the client device. To implement this idea, I am making use of the HTTP Content-Disposition response header and the HTML download attribute. The following is my sample code, where the server is implemented in Go:
HTML:
<a href="download" download>Download</a>
Server:
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
// Handle download request.
http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Disposition", "attachment; filename=\"log.txt\"")
w.Write([]byte("first message\n"))
time.Sleep(10 * time.Second)
// The following for-loop takes about 30 seconds to run on my dev machine.
for i := 0; i < 1000000; i++ {
timestamp := time.Now().Unix()
log(timestamp)
w.Write([]byte(fmt.Sprintf("%v\n", timestamp)))
time.Sleep(time.Microsecond)
}
log("done")
})
// Start HTTP server.
if err := http.ListenAndServe(":8080", nil); err != nil {
log(err)
}
}
func log(v ...interface{}) {
fmt.Println(v...)
}
This sample code works in that it successfully downloads all the content from the download handler when clicking on the "Download" link. However, I am observing the following behavior that I am unable to explain:
I have my browser configured to always ask where to save the downloaded files. When running the sample code above, Chrome opens the Save As window only after the 10 second sleep but before the for-loop is complete and in turn the handler function has returned. Why did Chrome not present the Save As window when the "first message" was sent before the 10 second sleep? What is different between the "first message" and the messages being sent in the for-loop that causes the Save As window to only open when the for-loop starts?
Aside: If FileSystemWritableFileStream had greater cross-browser support, I'd use that to stream dynamic server data directly into a file on the client side.
Go's http.ResponseWriter has a default 4KB buffer, defined at the Transport level:
type Transport struct {
// ...
// WriteBufferSize specifies the size of the write buffer used
// when writing to the transport.
// If zero, a default (currently 4KB) is used.
WriteBufferSize int
// ...
}
In some instances, when using standard responses, you can make use the Flush method by using type assertion with the http.Flusher interface to send the bytes right away:
if f, ok := w.(http.Flusher); ok {
f.Flush()
}
To have Firefox open the Save As window immediately after "first message" is sent, Ricardo Souza's answer appears to be all that's needed. To have Chrome do the same, the response's Content-Type header also needs to be set to anything other than the default text/plain (thanks to this SO answer). Example:
w.Header().Set("Content-Type", "application/octet-stream; charset=utf-8")

Get current directory address as localhost

This is continuation of question asked here (Provide link to iframe via js) as a second part. Here I am opening my iframe link. The iframe link opens up a PDF. I am currently running the code in localhost server which is why the address is http://127.0.0.1:5500. But when I upload it to the main server, this will be changed. My question is, since the link of the PDF is stored in the same directory as the index.html page. How do I automatically generate http://127.0.0.1:5500 or any other address depending on the hosting server. Such that it could be www.myhostingserver.come/myID/PDFIni.pdf and I do not have to manually enter the hosting address, rather just give : hostingaddress+"/PDFIni.pdf"?
<script>
...
...
let myIframe = document.getElementById("iframe");
if(myIframe.src != "http://127.0.0.1:5500/PDFIni.pdf")
{
console.log(myIframe.src);
myIframe.src = "http://127.0.0.1:5500/PDFIni.pdf";
}
Try to use document.location.hostname. For example:
var str = 'https://' + document.location.hostname + '/PDFIni.pdf';
if(myIframe.src != str) {
console.log(myIframe.src);
myIframe.src = str;
}

iOS 13 Swift 5 wkwebview - display image from documents directory into wkwebview real device

I have an app with downloaded images to be displayed in local html in WKWEBVIEW. Everything is working fine but it is not showing image on iPhone device
the html is
"\n<img src="images/d35fb6a3-8a21-4196-9616-ad2c6db60669/fd21b894-38c0-42c5-aa69-a938abe40e4b2467857252325869136.png">\n<img src="images/d35fb6a3-8a21-4196-9616-ad2c6db60669/c927a2a6-4ef0-481d-b27d-525cec7ed3814195490571216387044.png">\n"
matching to this HTML it is to be displayed in a wkwebview which gets displayed perfectly on simulator with the following code
let baseURL = Functions.FileIO.contentFolderURL()
static func contentFolderURL() -> URL? {
guard let folderURL = DataManager.shared.applicationDocumentsURL?.appendingPathComponent("content") else {
return nil
}
do {
let properties = try (folderURL as NSURL).resourceValues(forKeys: [URLResourceKey.isDirectoryKey])
if let isDirectory = properties[URLResourceKey.isDirectoryKey] as? Bool , isDirectory == false {
return nil
}
} catch let error as NSError where error.code != NSFileReadNoSuchFileError {
return nil
} catch {
// No folder, so we create it.
do {
try FileManager.default.createDirectory(atPath: folderURL.path, withIntermediateDirectories: true, attributes: nil)
} catch {
return nil
}
}
return folderURL
}
and then finally displaying
baseURL comes to be
Optional ▿ some :
file:///Users/paza/Library/Developer/CoreSimulator/Devices/D2204E03-8A8F-4EF4-8924-683CF519DD19/data/Containers/Data/Application/E4ED56CF-B247-4471-9F9B-23384FD6D6B3/Documents/content/
- _url : file:///Users/paza/Library/Developer/CoreSimulator/Devices/D2204E03-8A8F-4EF4-8924-683CF519DD19/data/Containers/Data/Application/E4ED56CF-B247-4471-9F9B-23384FD6D6B3/Documents/content/
self.webView?.loadHTMLString(HTML, baseURL: baseURL)
working in simulator below does not work in Device
as https://stackoverflow.com/a/52838445/3455426[ ]2
suggested I tried
self.webView?.loadFileURL(baseURL, allowingReadAccessTo: baseURL)
but the result this comes blank on real device
any leads will be appreciated , Thanks in advance
In WKWebview if we have to show HTML with Cached resources ,firstly we have to save the html string in HTML file in documents directory.
make sure ur cached resources path and the path of HTML file are same also , the cached resources are identified by the lastPathComponent only .
So the fault was the HTML which should have been
let HTML = "<html><body>\n<p><img src=\"fd21b894-38c0-42c5-aa69-a938abe40e4b2467857252325869136.png\"></p>\n<p><img src=\"c927a2a6-4ef0-481d-b27d-525cec7ed3814195490571216387044.png\"><br></p>\n</body></html>"
Specifically the last path component should be there .
Also I followed
https://en.it1352.com/article/9f185d4d185243cc92128148443ca660.html
here the explanation is almost perfect , I just saved in documents directory for swift.

Simple way to display image file with HTML forms section

I have been playing around with numerous go server snippets trying to figure out how I can display an image file within a HTML file or go HTTP template along with an html forms section. Basically, the biggest problem if I use a go template I cannot show an image along with html and still keep the project size small. It seems the only way to get the template to work is by organizing the code into a "typical go HTML project" which I am trying to avoid.
Is there any easy way (with only a couple files and not creating a "typical go web project file structure") to display HTML with an image inside a go template? I believe the problem below is basically with http handlers. Either I can have a text handler or image handler but not both? I need both so I can have user control from HTML form which image will be displayed.
If anyone can help I would really appreciate it.
R
Joe
--Revised
Sorry about being unclear. I have limited experience with go templates and I have seen many examples where people use go app project file structures that might include directories such as templates, img, etc. These directories are often 10 or more. Then they talk about using routes within apps and other things that I am timid to get into.
I just view what I want to do as much more simple. I have about 70 images. I just want a way where a user can click an html page that displays an image and just provide a number 1,2,3,4 as feedback depending on what image is being displayed.
I imagined that a single go program (1 file) could receive the number and once received change the img on the html page or allow the user to click a next hyperlink or something to bring up the next image and once it is over the program stops.
package main
import (
"fmt"
"html/template"
"log"
"net/http"
//"strings"
func img(w http.ResponseWriter, r *http.Request) {
//http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir("images/"))))
fmt.Println("method:", r.Method) //get request method
if r.Method == "GET" {
t, _ := template.ParseFiles("image.gtpl")
t.Execute(w, nil)
} else {
r.ParseForm()
// logic part of log in
fmt.Println("previmage:", r.Form["previmage"])
fmt.Println("nextimage:", r.Form["nextimage"])
}
}
func main() {
//http.HandleFunc("/", sayhelloName) // setting router rule
http.HandleFunc("/login", login)
err := http.ListenAndServe(":9090", nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
<html>
<head>
<title></title>
</head>
<body> //How to Loop Images based on user submit??
<img src="img/question4.png" alt="Cannot load image" style="width: 800px;height: 800px">
<form action="/login" method="post">
Username:<input type="text" name="previmage">
Password:<input type="password" name="nextimage">
<input type="submit" value="Login">
</form>
</body>
</html>
You have your http.Handle call, which registers the handler, inside the handler. That means every time a request comes in, it tries to register the handler again. That's not allowed (hence the error, which says explicitly that you cannot re-register the same route). You should be registering it in the same place you're registering the handler for the template, i.e. in main:
func main() {
http.HandleFunc("/login", login)
// Register handler correctly
// I changed the route to /img/ to match what you're using in your HTML
http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(http.Dir("images/"))))
err := http.ListenAndServe(":9090", nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

How do I modify elements of an HTML file with Go?

I've been trying to figure this out for a few days and I've kind of exhausted even the most effective of google searching. What I've been trying to do is to open a file of the type HTML and with Go's library (http://golang.org/x/net/html) modify the img tags and their source to a known directory and set of files. So far I've been able to find the elements using this,
//Open the file and return a variable called file.
file, _ = os.Open(file.Name())
//Create the doc
doc, err := html.Parse(file)
//Check for err when generating the doc
check(err)
//Look for tags with img using an anonymous function.
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "img" {
for _, img := range n.Attr {
if img.Key == "src" {
str := breakdownURL(img.Val) //Gets the ../../resource/(thing.h23.jpg) <-- That
//Creating a static address to add to the dynamic one
address := filepath.Join(filepath.Join("Resources", getFileNotExt(file)), str)
img.Val = address
break
}
}
}
for at := n.FirstChild; at != nil; at = at.NextSibling {
f(at)
}
}
f(doc)
That's been able to find the elements and append the correct directory but it's only modifying this doc file. I have no clue how to append it to the actual file. The only thought that I have is opening the doc as some kind of writing way and copying the new data from the doc to the file. Any help is greatly appreciated! Thank you so much for taking your time :).
You should definitely save the edited document.
First, open the file for read/write and truncate:
file, err := os.OpenFile("sample.html", os.O_RDWR | os.O_TRUNC, 0644)
And after you finish processing, override the original file:
html.Render(file, doc)