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:
Related
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
I'm trying to do a Grails webapp and now I'm trying to display all images in a folder.
To do that I have the following:
def display(){
def dir = new File("/tmp/images")
def list = []
dir.eachFileRecurse() { file ->
def avatarFilePath = new File(file.path)
response.setContentType("application/jpg")
OutputStream out = response.getOutputStream();
out.write(avatarFilePath.bytes);
out.close();
}
}
So using the code above I'm displaying one image using:
<img class="thumbnail" src='${createLink(controller: "images", action: "display")}' />
Using this code, I'm displaying one image.
How do I display all images in that folder?
Do I need to build a list? A list of what? A list of outputstream?
In that case, what should I put in my gsp file?
If the images folder was inside the app structure you could just create links to the image directly. In this case I think you need a controller action that output the contents of one file, and another action that get's the list of the images and request the file content.
class MyController {
private static final File IMAGES_DIR = new File('/tmp/images')
//get the list of files, to create links in the view
def listImages() {
[images: IMAGES_DIR.listFiles()]
}
//get the content of a image
def displayImage() {
File image = new File(IMAGES_DIR.getAbsoluteFilePath() + File.separator + params.img)
if(!image.exists()) {
response.status = 404
} else {
response.setContentType("application/jpg")
OutputStream out = response.getOutputStream();
out.write(avatarFilePath.bytes);
out.close();
}
}
}
And your gsp could do something like
<g:each in="${images}" var="img">
<img class="thumbnail" src='${createLink(controller: "myController", action: "displayImage", params:[img: img.name])}' />
</g:each>
P.S: the code is not tested, may need some adjust.
I have built and MVC3 application with a controller (Picture) and an action method (GetImage) that returns File contents (in my case a jpeg image)
public FileResult GetImage(int pictureID)
{
return File(Server.MapPath("~/Content/pic" + pictureID + ".jpg"), "image/jpeg");
}
When I access images in my views like
<a id="single_image"><img src="/Picture/1" /></a>
..I get the image displayed properly.
But when I apply jQuery Fancybox plugin to this image and click on the image, it displays the pop-up with byte[] data inside (something you would get when the file mime type is missing).
What am I doing wrong?
PS: Sorry I am unable to post any images but can email it.
Just get your images directly using Html.Content in your View.
Forms
<a id="single_image">
<img src="<%= Html.Content("~/Content/pic" + model.pictureID + ".jpg") %>" />
</a>
Razor
<a id="single_image">
<img src="#Html.Content("~/Content/pic" + model.pictureID + ".jpg")" />
</a>
EDIT
If you're dead set on using a picture controller, then I would recommend having your PictureController have the Index action return an ActionResult
public ActionResult Image(int id)
{
var dir = Server.MapPath("/Pictures");
var path = Path.Combine(dir, id + ".jpg");
return base.File(path, "image/jpeg");
}
This will however slow down your requests over a direct .jpg file access.
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.
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}"/>