im getting this error "image corrupt or truncated" on FF console when I try to display an image stored in my database. I´m using Grails and Hibernate.
I just want to display a user´s profile picture in my gsp page.
My domain class User has an attribute photo defined as byte[]
public class User {
private String userId;
private byte[] photo;
.
.
.
The user.hbm.xml mapping is :
< property name="photo" type="binary" column="PHOTO" not-null="false" />
This collumn is a BLOB on DB.
My gsp:
< div id="user-view-thumbnail-container">
<fieldset>
<legend>Photo Upload</legend>
<g:form action="uploadPhoto" method="post" enctype="multipart/form-data">
<label for="photo">Photo</label>
<input type="file" name="photo" id="photo" />
<input type="submit" class="buttons" value="Upload" />
</g:form>
</fieldset>
<g:if test="${user.photo}">
<img alt="User Photo" src="${createLink(controller:'profile', action:'profile_image', id:user.userId)}" />
</g:if>
</div>
ProfileController:
def uploadPhoto = {
def user = userService.getUser(authenticateService.principal())
def f = request.getFile('photo')
user.setPhoto(f.getBytes())
if (!user.save()) {
//doesn´t matter now
return;
}
redirect(action: 'index', model:[user: user])
}
def profile_image = {
def user = userService.getUser(params.id)
if (!user) {
response.sendError(404)
return;
}
response.setContentType(user.photo.contentType())//'image/png', 'image/jpeg', 'image/gif'
response.setContentLength(user.photo.size())
OutputStream out = response.getOutputStream();
out.write(user.photo);
out.close();
}
FYI: The picture is saved on DB correctly, I can see it, but I can´t show it on my gsp.
Any idea?
Thanks a lot guys,
Use blob type in the mapping :).
Related
I'm using unobtrusive ajax inside a kendo window to update a form once it's been filled in. The form should update the Id's of the DOM elements dynamically and also show the relative data inside the form as returned from the controller.
Let's start, here is the window element that houses the partial view which is a form:
#model Requirement
#{
int localId = Model.Id;
}
<div class="window-content">
<form method="post" data-ajax-url="/Home/Process_Requirement" data-ajax="true" data-ajax-method="post" data-ajax-loading="#spinner" data-ajax-update="#update-form-requirement" data-ajax-success="form_requirement_success">
<div id="update-form-requirement">
<partial name="_Form_Requirement" />
</div><!--/update-panel-->
<div class="window-footer">
<div class="container">
<div class="row no-gutters">
<div class="col">
<button type="submit" class="input-submit float-right">Save</button>
</div>
</div>
</div>
</div>
</form>
</div>
_Form_Requirement
#model Requirement
#{
int localId = Model.Id;
}
<div class="tab-content">
<div class="tab-pane fade show active" id="form-requirement-basic-#localId" role="tabpanel" aria-labelledby="requirement-tab">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="text" id="Id_#localId" name="Id" asp-for="Id" readonly />
<input type="text" id="CreatedUser_#localId" asp-for="CreatedUser" readonly />
<div class="container">
<div class="row">
<div class="col">
<div class="form-group">
<label>Vessel Type</label>
<kendo-dropdownlist name="VesselType"
for="VesselType"
id="VesselType_#localId"
datatextfield="TypeName"
datavaluefield="Id"
min-length="3"
style="width: 100%"
value-primitive="true"
option-label="Select vessel type"
footer-template="<button class='dropdown-button k-icon k-i-plus-outline' data-object-title='Add vessel type' data-object-function='_Window_Vessel_Type' onclick='open_data_window(this, event)'></button>"
filter="FilterType.Contains">
<datasource type="DataSourceTagHelperType.Ajax" page-size="80">
<transport>
<read url="/Vessel/ReadVesselTypes" />
</transport>
</datasource>
<popup-animation>
<open duration="300" effects="fadeIn" />
<close duration="300" effects="fadeOut" />
</popup-animation>
</kendo-dropdownlist>
</div>
</div>
</div>
</div>
</div>
</div>
When the form is submitted the controller action does the following:
/Home/Process_Requirement
public IActionResult Process_Requirement(Requirement model)
{
//Define the partial view we want
string modal = "_Form_Requirement";
//If the Id is 0 then create a new requirement
if (model.Id == 0)
{
if (ModelState.IsValid)
{
try {
_requirementService.InsertRequirement(model);
var getData = _requirementService.GetRequirement(model.Id);
return PartialView(modal, getData);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
else
{
try
{
_requirementService.UpdateRequirement(model);
return PartialView(modal, model);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return PartialView(modal);
}
So, when you first open a window to create a new requirement the localId is 0 because you're not editing one, that's expected behavior.
When you then fill in all the details and submit the form, the data is posted to the database and saved correctly but the model doesn't seem to update with the new data, for example the input for the Id remains as 0:
<input type="text" id="Id_#localId" name="Id" asp-for="Id" readonly />
yet the id for the input updates to the newly created id number. Why is this happening and can I do anything about it?
you have a bug. fix the last return
return PartialView(modal,model);
Is the Id primary key? If so, it is not recommend to change the primary key, you should add a new column to be the key.
the data is posted to the database and saved correctly but the model doesn't seem to update with the new data
This could be caused by the concurrency issues. I can't see your update code now, but you can
try to change your update code like this:
public async Task<IActionResult> Process_Requirement(Requirement model)
{
string modal = "_Form_Requirement";
if (model.Id == 0)
{
//....
}
else //to update
{
await TryUpdateModelAsync<Requirement>(_context.Requirements.FirstOrDefault(x => x.RId ==model.RId),"",c => c.Id, c => c.CreatedUser);
_context.SaveChanges();
return PartialView(modal, model);
}
return PartialView(modal);
}
My Model:
public class Requirement
{
[Key]
public int RId { get; set; } //new column
public int Id { get; set; }
public string CreatedUser { get; set; }
}
And in partial, pass the key with a hidden field:
<input type="text" asp-for="RId" hidden/>
<input type="text" id="Id_#localId" name="Id" asp-for="Id" />
<input type="text" id="CreatedUser_#localId" asp-for="CreatedUser" />
Result:
Following on from the example Access Device Camera with Blazor I would like to view the image on the same page. So far I have found several older examples using JS but I think I should stick to native Blazor.
I think this is the start, but have failed to reference the file that was selected.
<p>
<h1>My Camera App</h1>
</p>
<input #onchange="updateCanvas" id="capturedPic" type="file" accept="image/*" capture>
<br />
<canvas id="picCanvas"> </canvas>
<br />
<br />
#code
{
public void updateCanvas()
{
//Code to place captured image in the canvas;
}
}
Following the .NET5 introduction of InputFile, I have the following solution.
The max size of an image is 500K so the code converts the camera photo to a 100x100 thumbnail.
Many thanks to Daniel https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-5-release-candidate-1/ and Naveen https://www.learmoreseekmore.com/2020/10/blazor-webassembly-fileupload.html
<div>
<InputFile OnChange="#OnFileSelection"></InputFile>
<div class="row">
<img src="#imgUrl">
</div>
</div>
#code{
string imgUrl = string.Empty;
private async Task OnFileSelection(InputFileChangeEventArgs e)
{
IBrowserFile imgFile = e.File;
string imageType = imgFile.ContentType;
var resizedImageFile = await imgFile.RequestImageFileAsync(imageType, 100, 100);
var buffers = new byte[resizedImageFile.Size];
await resizedImageFile.OpenReadStream().ReadAsync(buffers);
imgUrl = $"data:{imageType};base64,{Convert.ToBase64String(buffers)}";
}
}
I have a requirement where I am asked to capture a fee applicable for a certain course. But the problem is for few courses the same fee is applicable to all type of users and for some courses profession-wise fee is applicable. eg if the user is a teacher then he has fewer fees than if he is an industry professional.
There are predefined professions in database.
Here is my current logic with code.
Depending on the radio button, I am toggling the proper div and particular logic at the back end.
<input type="radio" name="professionWiseFees" value="true">
<input type="radio" name="professionWiseFees" value="false">
<div id="totalAmount" class="hidden">
<input class="feeAmountOnly" name="feeAmount" type="text" />
</div>
<div id="professionWiseAmount" class="hidden">
<c:forEach items="${applicationScope.professionList}" var = "profession" >
Course Fee For ${profession.profession}
<input type="hidden" value="${profession.id}" name="profession" type="text"/>
<input class="feeAmoun2t" name="profession" type="text" />
</c:forEach>
<div>
Now I am checking which type of fees is applicable and filling the hashmap accordingly. if prefessionWiseFees is not applicable then adding the same fees to all the profession.
Boolean isProfessionWiseFeesApplicable = Boolean.parseBoolean(reqParams.get("professionWiseFees")[0]);
Map<Integer,Double> feeProfessionMap = new HashMap<>();
List<Profession> professions = (List<Profession>) servletContext.getAttribute("professionList");
if(isProfessionWiseFeesApplicable) {
String[] propfessionWiseFees = reqParams.get("profession");
// [1(profession_id),1000(fees),2,2000,3,7000], hence i+2 i=profession_id, i+1=fees
for(int i=0; i < propfessionWiseFees.length-1 ;i=i+2){
feeProfessionMap.put(Integer.valueOf(propfessionWiseFees[i]),Double.parseDouble(propfessionWiseFees[i+1]));
}
}
else {
double feeAmount = Double.parseDouble(reqParams.get("feeAmount")[0]);
for(Profession profession: professions){
feeProfessionMap.put(Integer.valueOf(profession.getId()),feeAmount);
}
}
courseBean.setProfessionWiseFees(feeProfessionMap);
courseBean.setProfessionWiseFees(isProfessionWiseFeesApplicable);
Model class:
public class CourseBean {
// few fields
private Map<Integer, Double> professionWiseFees; // <profession_id ,fees>
// all setters and getters
}
So How can I solve this problem elegantly? requestParam.get is making the code cluttery
If you think that
use of requestParam.get reducing readability and maintainability of code.
You may use Spring web binding.
First define a FeeForm bean:
public class FeeForm {
boolean isProfessionWiseFees;
ProfessionAmount[] professionAmounts;
Double feeAmount;
}
Then define the ProfessionAmount bean:
public class ProfessionAmount {
int profession;
double amount;
}
Then change the controller method in this way:
#RequestMapping(value = { "/test.html" }, method = RequestMethod.POST)
public String testOverflow(Map<String, Object> model,
FeeForm form)
{
Map<Integer,Double> feeProfessionMap = new HashMap<>();
List<Profession> professions = (List<Profession>) servletContext.getAttribute("professionList");
if(form.isProfessionWiseFees()) {
for(ProfessionAmount f : form.getProfessionAmounts()){
feeProfessionMap.put(f.getProfession(),f.getAmount());
}
}
else {
for(Profession profession: professions){
feeProfessionMap.put(profession.getId(),form.getFeeAmount());
}
}
HTML:
<input type="radio" name="professionWiseFees" value="true"> true
<input type="radio" name="professionWiseFees" value="false"> false
<div id="totalAmount" class="hidden">
<input class="feeAmountOnly" name="feeAmount" type="text" />
</div>
<div id="professionWiseAmount" class="hidden">
<c:forEach items="${applicationScope.professionList}" var = "profession" varStatus="status" >
Course Fee For ${profession.profession}
<input type="hidden" value="${profession.id}" name="professionAmounts[${status.index}].profession" type="text"/>
<input class="feeAmoun2t" value='0' name="professionAmounts[${status.index}].fee" type="text" />
</c:forEach>
<div>
You should come to the jsp holding flag in the model bean which indicate if the fees is applicable or not based on it play on the design and disable the inapplicable options .
or
use AJAx. you can use radio button and use onchange of them to check by ajax. if it's inapplicable return validation error message.
I want to know how I can upload an image and save its name in a database when using Codeigniter.
I am using a simple form tag for this, like:
<form action="./myaccount/index/" method="post" enctype="multipart/form-data">
<div>
<label for="pic">picture</label>
<input type="file" id="pic" name="pic" />
</div>
<input id="register-btn" name="register" type="submit" value="ok" class="input-text custom-btn">
</form>
Here's my controller:
public function index() {
$user = new User($_SESSION['user_id']);
if($this->input->post()){
$user->pic = $this->input->post('pic');
if($this->input->post('password') == $this->input->post('confirm')){
$user->password=md5(sha1(sha1($this->input->post('password'))));
$user->save();
$this->data['success'] = "done";
}else{
$this->errors[] = "error";
}
}
$this->data['user'] = $user;
$this->data['errors'] = $this->errors;
$this->template->set_layout('myaccount');
$this->template->build('profile',$this->data);
}
I checked the manual but I can't understand what they are doing.
Im' trying to make a controler function for this that will insert all the values in the database and also upload the image file.
I have a program that is developed in MVC 3 Razor Syntax but whenever I am posting to the controller with a file it doesn't work but if I just post to the controller without a file it works. What could be the problem ? Here's my Code:
#using (Html.BeginForm("UpdateFile", "AdministerFiles", FormMethod.Post,
new {enctype = "multipart/form-data"}))
{
string title = null;
string description = null;
string filename = null;
int dataid = 0;
int filesize = 0;
string filepath = null;
foreach (var fileDetails in ((RefDataLinks_mst[])#Model[1]))
{
title = fileDetails.DataTitle;
description = fileDetails.Description;
filename = fileDetails.DataFileName;
dataid = fileDetails.DataID;
filesize = fileDetails.FileSize;
filepath = fileDetails.DataFilePath;
}
<div id="updateLeftTopPart">
<label class="addFileLabel"for="title">Title : </label><textarea rows="3" cols="50" name="title" required>#title</textarea> <br /> <br />
</div>
<div id="updateRightTopPart">
<label for="description">Description : </label><textarea rows="2" cols="50" name="description" required>#description</textarea>
</div>
<div id="updateLeftPart">
<label>Existing File : </label><label>#filename</label>
</div>
<div id="updateUploadFile">
<label for="file">Upload New File Here :</label><input type="file" name="file" id="file"/>
</div>
<input type="hidden" value="#catid" name="catid"/>
<input type="hidden" value="#filename" name="existingFile"/>
<input type="hidden" value="#dataid" name="dataid"/>
<input type="hidden" value="#filesize" name="filesize"/>
<div id="updateActions">
<input type="submit" value="Update File" />
<input type="reset" value="Reset" />
</div>
}
These are the parameters of my Controller:
public ActionResult UpdateFile(HttpPostedFileBase file, int catid, int dataid, string title, string existingFile, string description, int filesize)
Whenever I post, The browser is saying that The connection to the server was reset while the page was loading. What could be the problem ?
Whenever I post, The browser is saying that The connection to the
server was reset while the page was loading. What could be the problem ?
The default 4MB limit that you could increase in your web.config using the <httpRuntime> element.
<!-- Allow files up to 100MB to be uploaded -->
<!-- Also increase the execution timeout as uploading
100 MB files could take some time and ASP.NET won't wait that long -->
<httpRuntime maxRequestLength="102400" executionTimeout="3600" />
By the way if you host your application in IIS 7+ you also need to adjust the requestLimits to the same value (in bytes this time):
<system.webServer>
<security>
<requestFiltering>
<!-- Limit file uploads to 100MB -->
<requestLimits maxAllowedContentLength="104857600" />
</requestFiltering>
</security>
</system.webServer>