problem rendering image in browser FileContentResult - image

I want to show an image from database
I have an action
public FileContentResult GetImage(string param)
{
type obj = _someRepository.GetType(param);
if (obj!= null && obj.Image!= null)
{
return File(obj.Image.ToArray(), obj.Image.MimeType);
}
return "some default image";
}
in the view I have
< img src="<%:Url.Action("GetImage","ControllerName",new { param= somevalue })%>" alt="some text"
width="100px" height="100px" />
I also have
(Html.BeginForm("actionname", "controllername", FormMethod.Post, new { enctype = "multipart/form-data" })
set.
The image data is fetched from the database But I can't see the image in the browser,
is there something that I am missing?

Here are the steps I would perform in order to isolate the problem. Start with a simple controller action which returns some hardcoded image somewhere from your harddrive:
public ActionResult GetImage(string param)
{
byte[] image = File.ReadAllBytes(#"c:\work\foo.png");
return File(image, "image/png");
}
Now navigate directly to /ControllerName/GetImage in your browser and you should see the image.
The next step is to fetch the image from the database and probably store it on your harddisk to ensure that it is a valid image:
type obj = _someRepository.GetType(param);
File.WriteAllBytes(#"c:\work\foo.png", obj.Image.ToArray());
Now checkout the generated file and see if it is valid. The last step is to ensure that the url generated in the <img> tag is the same as the one you used to test directly. Then look at FireBug's Net tab to see if the browser correctly requests the image and what does the server return.
Most probably the issue is that the byte array returned from the database is not valid image or it is empty.
As far as the form you have shown in your question, this is for uploading files, it has nothing to do with serving dynamic images from a controller action, so I don't see what relation it might have to your question.

Related

Set Image Source from Handler an subsequent page calls

I am setting the source for an image using a handler following this example:
Use Razor Page handler as image source.
The code looks like this:
<img src="StreamLink?handler=Thumb&filename=#thumbpath"/>
This works great for the first time the page is called.
However, there is an option to call the same page (Albumlist) again for a different year using this link:
<a class="yearlist" asp-page="/Albumlist" asp-route Section="#strYear.Key">#strYear.Value</a>
On the second call OnGetThumb is no longer executed.
Any ideas on how to set the image source for subsequent page calls?
Thanks
Th.
You need to make sure the url in src is correct.Here is a working demo:
Index.cshtml:
<a class="yearlist" asp-page="/Test2/Albumlist" Section="1">test</a>
Test2/Albumlist.cshtml:
<img src="Albumlist?handler=Thumb&filename=1" />
Test2/Albumlist.cshtml.cs:
public class AlbumlistModel : PageModel
{
public void OnGet()
{
}
public FileResult OnGetThumb(string fileName)
{
string path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/imgs/"+ fileName + ".jpg");
//Read the File data into Byte Array.
byte[] bytes = System.IO.File.ReadAllBytes(path);
return File(bytes, "image/png");
}
}
result:

Spring - download file and redirect

I have a download link on my page which works just fine but it doesn't refresh/redirects my page. Here's my code.
#RequestMapping(method = RequestMethod.POST, params = "exportToXML")
public String exportToXML(HttpServletResponse response, Model model, #ModelAttribute(FILTER_FORM) ScreenModel form,
BindingResult result, OutputStream out,
HttpSession session) throws IOException {
ZipOutputStream zipout;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
zipout = new ZipOutputStream(baos);
ZipEntry ze = new ZipEntry("file.xml");
zipout.putNextEntry(ze);
zipout.write(string.getBytes());
zipout.closeEntry();
zipout.close();
baos.close();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-disposition", "attachment; filename=xx.zip");
response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().close();
response.getOutputStream().flush();
return VIEW_NAME;
}
I've removed irrelevant pieces of code to make it a little bit shorter. I have also tried with #ResponseBody but it gives the same result as code above.
Any advice will be helpful
You can't download file and make refresh/redirect.
I'll try to explain causes. Request flow is illustrated here:
where yellow circle is your controller. When you return view name front controller looks for appropriate view template (simply jsp, tiles or other, depending on configured view resolver) gets response and write generated html (or not html) code to it.
In your case you perform actions:
response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().close();
response.getOutputStream().flush();
After that actions spring can't open response and write refreshed page to it (because you do it before).
So you can change your method signature to:
public void exportToXML(HttpServletResponse response, Model model, #ModelAttribute(FILTER_FORM) ScreenModel form,
BindingResult result, OutputStream out,
HttpSession session) throws IOException {
and delete last "return VIEW_NAME". Nothing will change.
You can:
response.setHeader("Refresh", "1; url = index");
This refresh the page after 1 second after response on URL: "index".
It will not. The browser opens the ms-excel contentType in a new window or you get a download prompt. The page that initiated download never get a chance to handle the redirect or page transition.
If the download + page refresh is desired, a JavaScript function could initiate the download and direct the user to next page, that page could say 'your download will commence shortly' or something similar.
You could after download, call a javascript function to submit to you controller and them show a different page.
I used the following structure to solve my problem. The function submit the form and back, in other words, you download the file and refresh the previous link. Using this solution, you can even show and hide messages errors with some template render, in my case, I used Thymeleaf.
To make the code more readable, I removed the Thymeleaf tags.
JS file:
function submitAndBack(formId) {
let formDoc = document.getElementById(formId);
formDoc.submit();
sleep(1000).then(function() {
window.history.back();
});
}
function sleep(milliseconds) {
return new Promise(function (resolve) {
setTimeout(resolve, milliseconds);
});
}
HTML form:
<form id="myForm" method="POST" action="/some/url">
<label for="inputText">Some info</label>
<input id="inputText" name="inputText" type="text">
<button onclick="submitAndBack('myForm')">
Submit
</button>
</form>
From LottaLava answer, I got the idea to solve a similar problem.
In JavaScript, after form submission, I wait for one and a half-second and then reload the page. The waiting time is to time for the backend to download the file (here exportToXML) and return the response and then in JavaScript refresh the page.
form.submit();
sleep(1500).then(function() {
document.location.reload();
});
Here form.submit() calls the controllers action, in your case exportToXML.
The sleep function is as follows:
function sleep(milliseconds) {
return new Promise(function (resolve) {
setTimeout(resolve, milliseconds);
});
}
The sleep function refers to here

how to display an image saved in my database

I have a database where I have saved image
How can I display the image ?
Now I display it like this
<img alt="#album.Room_number" src="#album.ImageData" />
But I get this:
You could use the Data URI scheme if your client browser supports it:
<img alt="#album.Room_number" src="data:image/jpeg;base64,#Convert.ToBase64String(album.ImageData)" />
If the browser doesn't support it you will have to create a controller action that queries the database and streams the image to the response:
public ActionResult Image(int id)
{
byte[] imageData = ... go and fetch the corresponding image data from the database
return File(imageData, "image/jpeg");
}
and then:
<img alt="#album.Room_number" src="#Url.Action("Image", new { id = album.ImageId })" />
Of course in this case you should not fetch the ImageData property within the initial request to avoid to unnecessary query it while not using it anymore in the view.
You need to create a controller action that serves the raw image data using return File(...).
You can then write <img src="#Url.Action(...)" />.

Dynamically display image (byte array) on jsp with Stripes

I am currently working with Stripes and I have an ActionBean that loads a specific User object JavaBean (Email, First Name, Last Name, Blob image) from my database according to a parameter in the url.
This ActionBean then forward to a JSP page that displays these information by using the ActionBean and accessing the User object instance (property of the ActionBean).
I have no problems displaying the text data (Email, First Name and Last Name) but I don't really know how I can display the Blob image (it's a byte array) dynamically.
Is there a way, maybe using a tag from the Stripes Tag lib to load a event (Resolution) that would load the image from the current ActionBean and display it when the page is loaded?
I thought I could call an Resolution (event) from the User JavaBean as the src of the tag but he doesn't seem to work...
public Resolution loadPicture(){
StreamingResolution sr = null;
return sr = new StreamingResolution("image/jpeg") {
public void stream(HttpServletResponse resp) throws Exception {
OutputStream os = resp.getOutputStream();
os.write(this.user.getBlob());
os.close();
}
};
}
Thanks in advance!
That's not how HTTP and HTML works. A request is used to load the HTML code. This HTML code contains various <img src="..." /> tags, and a new request is made to load each image. You must generate HTML with img tags that have their src point to a Stripes action which will load the image and stream it to the response.
A StreamingResolution is the right approach to implement this action, but the action will have to be called from another request.

Salesforce - Is it possible to display image file from ContentVersion to custom visualforce page?

I wrote one simple Visualforce page that let user upload an image file then
save the file to ContentVersion object.
Now I want to display the saved image in my custom visualforce page. Is it even possible?
Looks like <apex:image> cannot be used. Also <img href="{!cv.contentVersion}"...> had no luck.
The real problem is I did upload the image file successfully but what is the URL to it?
I tested with random URL outside on google and I can display the image (like /../..some.jpg"). But I can't figure out what is the absolute URL for the image file that has been uploaded to contentversion.
NOTE: This is not static resource as my users may upload image to change their user image often.
Code
public with sharing class ImageUploadTestController {
public blob file { get; set; }
public String imageFilePath { get; set; }
public ContentVersion cv { get; set; }
public ImageUploadTestController() {
cv = [select id, versionData, title, pathOnClient FROM ContentVersion limit 1];
}
//fill out the inputFile field and press go. This will upload file to the server
public PageReference go() {
ContentVersion v = new ContentVersion();
v.versionData = file;
v.title = 'some title';
v.pathOnClient ='/foo.jpeg';
insert v;
return new PageReference('/' + v.id);
}
//v.id sample
//069A00000009Ux3
}//end class
Visualforce page
<apex:page controller="ImageUploadTestController">
<apex:form >
<apex:inputFile value="{!file}" />
<apex:commandbutton action="{!go}" value="go"/>
</apex:form>
<!-- none of below works!! :( -->
{!cv.title} {!cv.pathOnClient}
<apex:image value="/069A00000009Ux3" width="220" height="55"/>
</apex:page>
I don't believe its possible to serve it from content currently The format provided by ScottW works for Documents.
The other option I've done is upload a zip file containing my images to the Static Resources which can then be referenced.
This should work:
public PageReference getContent(){
String html = ApexPages.currentPage().getParameters().get('html');
PageReference redirection = null;
redirection = new PageReference('/sfc/servlet.shepherd/version/download/' + contentVersion.Id);
redirection.setRedirect(true);
return redirection;
}
Based on my experience, "thegogz"is correct - it is not currently possible to render images directly from Content. As others have indicated, rendering from Documents and/or Static Resources does work, and IMHO using Documents is preferable because you can access the URL, binary data, etc. programmatically in Apex.
The image is shown using "/servlet/servlet.FileDownload?file=" in tag by using URL attribute.
Example : <apex:image URL="/servlet/servlet.FileDownload?file={!recordId}"/>
for more information,
visit Displaying Images in a Visual Force Page
Try <apex:image URL="/servlet/servlet.FileDownload?file={!recordId}"/>

Resources