Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HTML] how to load local image by html output #884

Closed
Olvi73 opened this issue Mar 27, 2022 · 33 comments
Closed

[HTML] how to load local image by html output #884

Olvi73 opened this issue Mar 27, 2022 · 33 comments
Labels
bug Something isn't working
Milestone

Comments

@Olvi73
Copy link

Olvi73 commented Mar 27, 2022

Describe the bug

When I run the gradio code, it will running on local URL: http://127.0.0.1:7860/, in this way I can't use html code like this to load a image

    html = (
            "<div >"
            + "<img  src='./tmp/1.jpg 'alt='image One'>"
            + "</div>"
    )

or use absolute path

html = (
            "<div >"
            + "<img  src='file://F:\\tmp\\1.jpg 'alt='image One'>"
            + "</div>"
    )

Reproduction

import gradio as gr

title = "test"

def inference(text):
    html = (
            "<div >"
            "<img  src='./tmp/1.jpg 'alt='image One'>"
            + "</div>"
    )
    return html

gr.Interface(
    inference,
    gr.inputs.Textbox(placeholder="Enter sentence here..."),
    outputs=["html"],
    title=title,
    allow_flagging="never",

).launch(enable_queue=True)

Screenshot

Logs

No response

System Info

gradio version:2.8.9
OS: win11
browser:Chrome 99.0.4844.82

Severity

annoyance

@Olvi73 Olvi73 added the bug Something isn't working label Mar 27, 2022
@abidlabs
Copy link
Member

Hi @Olvi73 thanks for creating this issue! We are going to take a look at it soon

@abidlabs abidlabs added this to the 3.0 milestone Apr 21, 2022
@abidlabs
Copy link
Member

Hi @Olvi73, you can access relative files by adding the prefix file/ to the path.

So if the code to your Gradio app is in a file called app.py, and you have an image called lion.jpg in the same directory:
---- app.py
---- lion.jpg

Then the code in app.py would look like:

import gradio as gr

title = "test"

def inference(text):
    html = (
            "<div >"
            "<img  src='file/lion.jpg' alt='image One'>"
            + "</div>"
    )
    return html

gr.Interface(
    inference,
    gr.inputs.Textbox(placeholder="Enter sentence here..."),
    outputs=["html"],
    title=title,
    allow_flagging="never",

).launch(enable_queue=True)

Note that for security reasons, any file that is included in your app must be in the same directory or in a child directory of app.py.

@jamsnrihk
Copy link

Can i add a logo picture near title text?

@AbubakrChan
Copy link

    gr.inputs.Textbox(placeholder="Enter sentence here..."),
    outputs=["html"],
    title=title,

SAME QUESTIONS

LET ME KNOW IF YOU FOUND ANY SOLUTION YET!

THANKS

@AbubakrChan
Copy link

Can i add a logo picture near title text?

.

@tlabarta
Copy link

tlabarta commented Mar 26, 2024

Hello, this issue still seems to exist for me, I get a 403 forbidden error. According to your response @abidlabs, it should work if I add the "file/" prefix and if both files are in the same directory, which is the case in my project. Please help.

File structure:
-directoryA
--testfile.py
-directoryA
-app.py
-Fraunhofer_HHI.png
-README.md

Code:

with gr.Blocks(theme=theme, css=css, head=head_js) as demo:
    gr.HTML(value="<img src='file/Fraunhofer_HHI.png'>", elem_id="img_test")

if __name__ == "__main__":
    demo.launch()

Error Message from Firefox console:

GET
http://127.0.0.1:7860/file/Fraunhofer_HHI.png
[HTTP/1.1 403 Forbidden 3ms]

@freddyaboulton
Copy link
Collaborator

Hi @tlabarta this is an old thread which predates the file access rules of gradio 4.0. You need to specify the file paths you want to show with allowed_paths.
This is the latest guide on this: https://www.gradio.app/guides/sharing-your-app#security-and-file-access

@tlabarta
Copy link

tlabarta commented Apr 2, 2024

@freddyaboulton Thank you for your reply. Unfortunately, this has not solved my issue.
File structure:
-app.py
-static
--Fraunhofer_HHI.png

No matter if I try set_static_paths or allowed_paths.

with gr.Blocks(theme=theme, css=css, head=head_js) as demo:
    gr.set_static_paths(paths=["static/Fraunhofer_HHI.png"])
    gr.Markdown("<img src='static/Fraunhofer_HHI.png' alt='Fraunhofer HHI Logo' height='100' width='400'>")

if __name__ == "__main__":
    demo.launch(allowed_paths=["static/Fraunhofer_HHI.png"])

I get:

GET
http://127.0.0.1:7860/files/static/Fraunhofer_HHI.png
[HTTP/1.1 404 Not Found 1ms]

@freddyaboulton
Copy link
Collaborator

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

@tlabarta
Copy link

tlabarta commented Apr 3, 2024

@freddyaboulton This worked now, thanks a lot!

@thormtl
Copy link

thormtl commented Apr 12, 2024

Hi @tlabarta this is an old thread which predates the file access rules of gradio 4.0. You need to specify the file paths you want to show with allowed_paths. This is the latest guide on this: https://www.gradio.app/guides/sharing-your-app#security-and-file-access

Thanks so much for this comment here. Literally saved me a lot of time and headache!

@freddyaboulton
Copy link
Collaborator

It's on my plate to make this process less confusing but glad this thread is useful in the meantime!

@yyxx1997
Copy link

yyxx1997 commented Apr 22, 2024

Thank you very much for answering my questions and it worked in my project.
But currently, I still face a dilemma. I hope the gradio page can display my separately written markdown document.
for example, the organization of project documents is as follows:

-rootpath
--assets
---pic.png
--app.py
--readme.md

According to your opinion, the readme.md document must use the following methods to display pic.png on the webpage:<img src='/file=assets/pic.png'>
However, this will result in images not being displayed when viewing readme.md documents separately.
This is a dilemma. Is there any good way to solve it?

@agn-7
Copy link

agn-7 commented Jun 14, 2024

I have the same issue and none of the above answers worked!

I have a simple Gradio UI and need a header loading a local image which is next to the .py file. It can be loaded using the gr.Image() but since I want to apply some changes like its size I need gr.HTML() or gr.Markdown(). However. I have the same issue for loading the image locally!

import gradio as gr

def greet(name):
    return f"Hello {name}!"

image_path = "flytask_logo.png"

with gr.Blocks() as demo:
    html_header = f"""
    <div style="text-align: center;">
        <img src="{image_path}" alt="Header Image" width="200" height="100">
    </div>
    """
    gr.HTML(html_header)

    name_input = gr.Textbox(label="Enter your name:")
    submit_button = gr.Button("Submit")
    output = gr.Textbox(label="Greeting:")

    submit_button.click(fn=greet, inputs=name_input, outputs=output)

demo.launch()

I also tested with image_path = "file=flytask_logo.png" or image_path = "file/flytask_logo.png" or image_path = "/file=flytask_logo.png" without result!

@songfeng
Copy link

@freddyaboulton This worked now, thanks a lot!

Which version of gradio does this solution with? Thx

@akudnaver
Copy link

I had no luck so far adding an image to the gradio interface for my chatbot , with the below method.

Looking for a solution for this problem..

Path to the chatbot image in the Colab project directory

chatbot_image_path = "/content/chatbot_image.jpg"

Create a custom CSS string

custom_css = """
.input_box textarea {
background-color: #f0f0f0;
border: 1px solid #ccc;
font-size: 16px;
}
.output_box {
background-color: #e6f7ff;
border: 1px solid #007bff;
padding: 10px;
font-size: 16px;
color: #007bff;
}
.gr-button {
background-color: #007bff;
color: white;
border-radius: 5px;
}
.chatbot-image {
display: block;
margin-left: auto;
margin-right: auto;
width: 564px; /* Adjust the width as needed /
height: 423x; /
Maintain aspect ratio */
border-radius: 50%;
}
"""

Create Gradio interface

iface = gr.Interface(
fn=chatbot_interface,

# inputs='text',
inputs=gr.Textbox(placeholder="Enter your query and get a response from the AI chatbot."),
outputs='text',
title="AI Chatbot",
# description="Enter your query and get a response from the AI chatbot.",
theme=gr.themes.Monochrome(),
css=custom_css,
description=f"""
<div style="text-align: center;">
    <img src='{chatbot_image_path}' class="chatbot-image">
</div>
"""

)

@agn-7
Copy link

agn-7 commented Jul 15, 2024

@akudnaver

The issue you have is related to the image path and one possible solution is using gr.set_static_paths() as follows:

gr.set_static_paths(paths=["static/images/"])
image_path = "static/images/logo.png"
gr.HTML(f"""<img src="/file={image_path}" width="100" height="100">""")

Note: you would need to create a /static folder within the root of your project.

For more details check this SO post out.

@akudnaver
Copy link

akudnaver commented Jul 15, 2024

@agn-7
So instead of the gr.html method, I tried the gr.Markdown along with the suggestion from @freddyaboulton .

Your solution seems to work with 'gr.Markdown' method.

gr.Markdown("<img src='/file=/content/chatbot_image.jpg' alt='Chatbot Logo' height='100' width='400'>")

Thanks a lot @agn-7 , @freddyaboulton for your help.

@anirbanbasu
Copy link
Contributor

anirbanbasu commented Aug 17, 2024

@freddyaboulton

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

This works for me in the sense that I can request the URL: http://host:port/file=static_allowed_path_to_file but this does not render as an image (using the <img> tag in gr.HTML) when the static_allowed_path_to_file is actually an SVG. Instead, navigating to that URL (http://host:port/file=static_allowed_path_to_file) ends up downloading the correct file. Perhaps, the HTTP response headers from gradio are incorrect? Or, am I missing something?

@snapfast
Copy link

snapfast commented Sep 3, 2024

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

Not working anymore.

@JSchmie
Copy link

JSchmie commented Sep 12, 2024

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

Not working anymore.

Is there a simple workaround I could try? It’s a bit frustrating that my app isn’t showing the right logo anymore. Thanks so much for any help!

@snapfast
Copy link

snapfast commented Sep 12, 2024

@JSchmie
I did solve this, but it is little elaborate solution.

main.py

def load_css():
    with open('styles.css', 'r') as file:
        css_content = file.read()
    return css_content


with gr.Blocks(css=load_css(), theme=theme) as demo:
     gr.Image("./images/main-logo.png", elem_classes="logo-image", interactive=False, container=False, show_share_button=False, show_download_button=False, show_fullscreen_button=False, show_label=False)

styles.css

.logo-image {
    height: 70px;
    position: absolute;
    left: 10px;
}

@JSchmie
Copy link

JSchmie commented Sep 13, 2024

Hi @snapfast, thank you for your prompt response!

I tested the solution you provided, but I found a quicker workaround in my case. It appears that .svg images don't render properly for me, while .png images work flawlessly.

For instance, the following code doesn't display the image as expected:

import gradio as gr

with gr.Blocks() as demo:
    gr.HTML("<img src='/file=./logo.svg' alt='image One'>")
    
demo.launch()

However, switching to .png works without any issues:

import gradio as gr

with gr.Blocks() as demo:
    gr.HTML("<img src='/file=./logo.png' alt='image One'>")
    
demo.launch()

Additionally, I noticed that I don't need to set allowed_paths for this to work locally. It seems like this configuration becomes necessary only when deploying the app behind a reverse proxy, such as nginx.

@abidlabs, it would be extremely helpful if the documentation could include a brief guide on serving HTML resources, especially clarifying the behavior with different image formats and deployment scenarios.

Thanks a lot again for your help, and I just want to add that I really enjoy working with Gradio. It's an amazing tool!

@abidlabs
Copy link
Member

Thanks @JSchmie for pointing that out. This has to do with how we serve svg files (for security reasons, we add a content disposition header which prevents it from being served inline). I'm looking into whether we can relax this for security reasons

@0xfff010
Copy link

import base64

Function of image to string base64

def get_logo_base64():
with open("logo.png", "rb") as image_file:
return "data:image/png;base64," + base64.b64encode(image_file.read()).decode('utf-8')

In front Gradio

logo_base64 = get_logo_base64()
gr.HTML(f"

")

IMG_4737

@YzYhhhstudy
Copy link

hey guys, I would like to add a solution by loading the photo:

We can upload the photo to a server and just copy the photo link!

I use https://picui.cn/
image

just upload our photo, and get a link, and then paste the link into src
image

It just works as loading the local image

Hope this way can help someone...

Best regards

@meng-hui
Copy link

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

Not working anymore.

We need to know for what versions of gradio it used to work for.

I'm using gradio 5.4 and can't seem to get any local image to display.

I'm using gr.Markdown

gr.Markdown(
    "<div>"
    '<img style="float:left; margin: 5px;" src="/file=logo.png">'
    "</div>"
)

blocks.launch(allowed_paths=["logo.png"])

There is no nested folders..

@abidlabs
Copy link
Member

In Gradio 5, the route is /gradio_app/file=

@Jacob-Barhak
Copy link

The /file={path} endpoint option is working with gradio version 4.4.1 . It is no longer working with version 5.6.0.

And @abidlabs - did you just change the format of how to call the file in gradio version 5 to /gradio_app/file= instead of /file= then it does not seem to work when I use http://127.0.0.1:7860/gradio_app/file=static/a.jpg however when I downgrade to version 4.4.1 I am able to access the same file from the browser using http://127.0.0.1:7860/file=static/a.jpg

This option is not well documented for sure. I learned about it from this discussion as a solution suggested by @abidlabs to avoid needing to run fastapi alongside gradio to serve files.

I understand there are some security concerns, yet if you allow using a file either by set_static_paths or allowed_paths in launch then the user declared those as safe for the application. So not allowing these seems to be contradictory to the [security and file access documentation] (https://www.gradio.app/guides/file-access). So something needs to change to keep users informed.

If version 5.6 changes something significant that breaks old behavior, perhaps it a good idea to document this in the security guide. However, this option of exposing static files is sometimes important to communicate with other APIs that require files passed through a URL.

I understand one can work around this by creating a specific end point to serve a file like in the echo example in this accessing a network request directly section in this page or create request objects that pass the image payload. However, it is so much simpler and so much like serving static files in flask and fastapi that one should consider allowing it in gradio.

Hopefully you will fix it with future versions and make it work rather than deprecating the option. If you keep it, please consider enhancing the docs - I am happy to help if you need it if I know what you plan to do.

@abidlabs
Copy link
Member

Hi @Jacob-Barhak, this is working for me:

import gradio as gr

with gr.Blocks() as demo:
    gr.HTML("<img src='/gradio_api/file=cat.jpg'>")

demo.launch(allowed_paths=["cat.jpg"])

where cat.jpg is in the same directory as the Gradio app. If a similar app isn't working for you, can you provide a minimal repro including the files/directory structure?

@abidlabs
Copy link
Member

If version 5.6 changes something significant that breaks old behavior, perhaps it a good idea to document this in the security guide. However, this option of exposing static files is sometimes important to communicate with other APIs that require files passed through a URL.

For now, I've listed it in the breaking changes here: #9463

Feel free to open a PR to add it to a relevant sections in the docs @Jacob-Barhak and we are happy to review

@Jacob-Barhak
Copy link

Jacob-Barhak commented Nov 27, 2024

Ok @abidlabs

The #9463 issue explains what is happening. During development and before deploying gradio I am testing it locally and this is probably the source of the problem. I am using http://127.0.0.1:7860/file=static/a.jpg to access a local file and test that it works externally.
The change you made is documented under the title "Gradio does not allow URLs that resolve to local files".

So it seems you blocked the ability to run things locally for debugging and development. The code that exposes an image in a static file in 4.44.1 successfully is blocked in 5.6.0 and one can spend hours figuring out what is going on.

I understand you have security concerns, yet can you at least leave a debug option that allows local development that allows accessing files on the localhost?

Other platforms such as fastapi or flask allow this - some have a specific flag to mention one is debugging.

I was confused for a long time why things are not working as written before I posted this issue and you explained it.

Not sure what is the best solution here - for now may just use an earlier version for development - although this is not ideal...

Thanks for the quick reply.

@Pokora22
Copy link

In Gradio 5, the route is /gradio_app/file=

Just a note - you made a typo on this. It's /gradio_api/file=
You corrected with the code snippet below, but to anybody not reading carefully, they might miss. Worth a comment edit :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests