I use spring mvc and JPA in my project. I get file as byte[] and save in Database. but when I want to display in <img tag of html it don't display.
my entity is:
class Photo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
#Lob
private byte[] profilePic;
// getter and setter
}
value in Database is:
but my server response is:
{
"id": 4,
"title": "pic 1",
"profilePic": "ZGF0YTppb...VFtQ0M=",
}
and display in html:
<img src='ZGF0YTppb...VFtQ0M=' />
//or
<img src='data:image/jpeg;base64,ZGF0YTppb...VFtQ0M=' />
What to do to display the photo?
thanks
Assuming it's base64 encoded:
<img src='data:image/jpeg;base64,ZGF0YTppb...VFtQ0M=' />
Basically you can use data urls with this format depending on what content [type] you want to display:
data:[<mime type>][;charset=<charset>][;base64],<encoded data>
HTML:
<img id="profileImg" src="">
JS:
document.getElementById("profileImg").src = "data:image/png;base64," + profilePic;
This assumes that your image is stored in PNG format (and base64 encoded). For other image format (JPEG, etc.), you need to change the MIME type ("image/..." part) in the URL.
I'm trying to interpolate a value of photo within Vue. Here is the components:
Explaination: We are defining a data set as null. We are then, performing a post method to a backend database where we get photo,email,name and id. Everything works fine until the photo value. As you can see I performed a slice method on the string which removed unnecessary data. The output of this is just the file name.
<script>
export default {
data() {
return {
photo: null,
email: null,
name: null,
id: null
};
},
created() {
this.axios
.post("http://127.0.0.1:8000/api/auth/me", "body", {
headers: axiosHeader
})
.then(response => {
console.log(response.data);
this.name = response.data.name;
this.email = response.data.email;
this.id = response.data.id;
this.photo = "#/photodatabase/" + response.data.photo.slice(37, 56);
console.log(this.photo);
})
.catch(error => {
console.log(error);
});
}
};
</script>
The value I got is #/photodatabase/041120_09_24_03.jpg when I console.log(this.photo) which is the correct value. However when I try to interpolate it like:
<img v-else-if="photo != null" :src="photo"
height="200px" width="200px" />
The image doesn't show. When I inspected element, you could see on the img tag that the value was #/photodatabase/041120_09_24_03.jpg which was the correct value.
I tried interpolating like this:
<img v-else-if="photo != null" :src="`${photo}`"
height="200px" width="200px" />
and it still doesn't work. However when I didn't interpolate the value of photo, didn't use the v-bind shorthand : and just copied and pasted the value of photo to the src prop like this:
<img
v-else-if="photo != null"
src="#/photodatabase/041120_09_24_03.jpg"
height="200px"
width="200px"
/>
Then it works. What am I missing here?
Because is dynamic image src
must photo be absolute URL Like: http://127.0.0.1:8000/photodatabase/041120_09_24_03.jpg
or
if in the same server
/photodatabase/041120_09_24_03.jpg
or you can easily send absolute URL on response.
I believe that this isn't the correct URL #/photodatabase/041120_09_24_03.jpg
You've wrote "it still doesn't work" so You get "404 Not found" error?
That link should lead to Your backend (static asset or Laravel controller).
# is rewritten by Webpack during compilation time to Your public url - it won't work as a dynamic path in runtime...
This code
<img src="#/photodatabase/041120_09_24_03.jpg" />
...should become something else after compilation. Inspect it.
It could be something like that:
<img src="/static/photodatabase/041120_09_24_03.jpg" />
So if You didn't map # in vue-router, nor in Laravels routes, then You should change # in that link. You can try simply /photodatabase/041120_09_24_03.jpg
Try using the require handler
<img v-else-if="photo != null" :src="require(${photo})"
height="200px" width="200px" />
I'm parsing an RSS feed using rss-parser, displaying the results in a list.
The data is added to the state as such:
async getJobsData() {
let feed = await parser.parseURL(
"https://weworkremotely.com/categories/remote-design-jobs.rss"
);
this.setState({ data: feed.items });
}
The text fields are easy, as these come in as <pubDate>Mon, 20 May 2019 10:36:42 +0000</pubDate>, and are added to their respective list items using <span key={index}>{data.pubDate}</span>.
The response for images is formatted differently though. It's inserted into the generic content response, as the first item.
title: [...]
pubDate: [...]
content: "<img src="https://we-work-remotely.imgix.net/logos/0015/7503/logo.gif?ixlib=rails-2.1.3&w=50&h=50&dpr=2&fit=fill&auto=compress" alt="Logo.gif?ixlib=rails 2.1" />
How would I extract only the URL (https://we-work-remotely.imgix.net/logos/0015/7503/logo.gif?) from that field?
You can use DOMParser to parse the text representation into a DOM.
The code snippet below will print img.src.
const imgText = `<img src="https://we-work-remotely.imgix.net/logos/0015/7503/logo.gif?ixlib=rails-2.1.3&w=50&h=50&dpr=2&fit=fill&auto=compress" alt="Logo.gif?ixlib=rails 2.1" />`
const doc = new DOMParser().parseFromString(imgText, 'text/html')
console.log(doc.body.firstElementChild.src)
You can use HTML parser e.g. https://www.npmjs.com/package/fast-html-parser and get the src attribute.
When I upload files with dropzone it adds them to the database, but they don't have a file, just an ID and creation date. I think the view is the problem but I've tried tons of stuff and I can't figure it out. See my edit below for a more detailed account.
Here is the view
#login_required(login_url='/dashboard-login/')
def dashboard(request):
current_user = request.user
current_client = request.user.client
files = ClientUpload.objects.filter(client=current_client)
form = UploadFileForm()
if request.method == 'POST':
if request.FILES is None:
logger = logging.getLogger(__name__)
logger.warning("No files were attached to the upload.")
return HttpResponseBadRequest('No Files Attached.')
if form.is_valid():
upload = form.save()
form = UploadFileForm(request.POST, request.FILES)
else:
uploaded_files = [request.FILES.get('file_upload[%d]' % i)
for i in range(0, len(request.FILES))]
for f in uploaded_files:
client_upload = ClientUpload.objects.create(client=current_client, file_upload=f)
#for key in request.FILES:
# cupload = ClientUpload.objects.create(client=current_client, file_upload=request.FILES[key])
logger = logging.getLogger(__name__)
logger.debug(request.FILES)
logger.info("File(s) uploaded from " + current_client.company)
return HttpResponseRedirect(reverse('dashboard'))
data = {'form': form, 'client': current_client, 'files': files}
return render_to_response('dashboard.html', data, context_instance=RequestContext(request))
Here are my dz options:
url: '127.0.0.1:8003/dashboard/',
method: "post",
withCredentials: false,
parallelUploads: 12,
uploadMultiple: true,
maxFilesize: 256*4*2,
paramName: "file_upload",
createImageThumbnails: true,
maxThumbnailFilesize: 20,
thumbnailWidth: 100,
thumbnailHeight: 100,
maxFiles: 12,
params: {},
clickable: true,
ignoreHiddenFiles: true,
acceptedFiles: null,
acceptedMimeTypes: null,
autoProcessQueue: false,
addRemoveLinks: true,
previewsContainer: null,
dictDefaultMessage: "Drop files here to upload",
dictFallbackMessage: "Your browser does not support drag and drop file uploads.",
dictFallbackText: "Please use the fallback form below to upload your files.",
dictFileTooBig: "File is too big ({{filesize}}MB). Max filesize: {{maxFilesize}}MB.",
dictInvalidFileType: "You can't upload files of this type.",
dictResponseError: "Server responded with {{statusCode}} code.",
dictCancelUpload: "Cancel upload",
dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
dictRemoveFile: "Remove",
dictRemoveFileConfirmation: null,
dictMaxFilesExceeded: "You can only upload {{maxFiles}} files.",
And here is the template:
{% load i18n %}
{% load staticfiles %}
{% load crispy_forms_tags %}
<link href="{% static 'css/dropzone2.css' %}" type="text/css" rel="stylesheet"/>
<form class="dropzone" id="myDropzone" method="post" action="{% url 'dashboard' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</form>
<button class="upload-control btn-success btn" type="submit" id='submit-all' onclick="document.getElementById('myDropzone').submit()">
<i class="glyphicon glyphicon-upload"></i>
<span>{% trans 'Submit' %}</span>
</button>
<style>
.upload-control {
margin-top: 10px;
margin-bottom: 0px;
}
</style>
<script src="{% static 'js/dropzone.js' %}"></script>
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
<script type="text/javascript">
Dropzone.autoDiscover = false
$(document).ready(function() {
Dropzone.options.myDropzone = {
init : function() {
var submitButton = document.querySelector("#submit-all")
myDropzone = this;
submitButton.addEventListener("click", function(e) {
e.stopPropagation();
e.preventDefault();
myDropzone.processQueue();
});
this.on("sendingmultiple", function() {
// Figure out what I want here or if I want at all
});
this.on("successmultiple", function(files, response) {
window.location.reload();
});
this.on("errormultiple", function(files, response) {
// Figure out what I want here or if I want at all
});
}
// Do I need this?
//myDropzone.on('success', myDropzone.processQueue.bind(myDropzone));
};
});
</script>
EDIT:
It works now after adding http:// to the url setting. But when I upload a file it is added to the database, but the file field is blank. The multivaluedict shows the file when I print it out, but when it is saved to the database the file field has nothing in it.
When I upload one file I get this in request.FILES:
<MultiValueDict: {u'file_upload[]': [<InMemoryUploadedFile: normal.PNG (image/png)>]}>
When I upload two I get this in request.FILES:
<MultiValueDict: {u'file_upload[]': [<TemporaryUploadedFile: normal.PNG (image/png)>]}>
Despite being two files it only shows the one, but adds them both to the database (both without files and just ID and creation date). Also what is TemporaryUploadedFile and InMemoryUploadedFile?
It should have indexes in the u'file_upload[]' when I upload more than one but it doesn't. I have the settings correct for uploading multiples.
But I can't seem to get them out of the MultiValueDict. And when I try something like:
for upload in request.FILES:
client_upload = ClientUpload.objects.create(client=current_client, file_upload=upload)
I run into that problem where the admin panel shows an ID and time but no file. It happens when uploading one or more. I'm not sure what the difference is between InMemoryUploadedfile and TemporaryUploadedFile either. How can I extract the files from the MultiValueDict? get() is not working, with the list comp I just get an empty list.
The other odd thing, is when I upload certain files the MultiValueDict is empty, and with others it is not. Also it seems that my view gets called more than once (according to the log outputs) and that is normal, except it should be a post then redirect to a get, but it seems to have more than one post request. I checked the dev tools in chrome and I only see one, but oddly it outputs my log statement twice for every time I submit. I know the issue is probably in my view but I've tried a ton of stuff and can't figure out what is wrong.
Anybody have any ideas?
I'm working with Dropzone and Django myself for creating Image objects for each file uploaded, which seems to be akin to what you want to do. I'd like to point out some things that I've experienced and show you how I'm doing it to see if that helps.
What you need
The things that you need in order to create a record in the Database for files uploaded with Dropzone is:
The Dropzone HTML form
The Javascript initialization of Dropzone.
A Django View to handle the uploaded files.
I don't understand what you're doing with the Form (is it just validating?) but it seems to be unnecessary. You don't need it (and don't use it) to actually save the file.
Accessing the uploaded files
First lets talk about how to access the files in request.FILES. By setting uploadMultiple: true on your Dropzone configuration you condition Dropzone not to send dzfile but to send each file represented as dzfile[%d] (i.e. dzfile[0], dzfile[1], etc).
Even if that was not the case you're using request.FILES like if it was a list (for f in request.FILES), but like you point out it's actually a dict.
Here's what Python shows when I print request.FILES:
<MultiValueDict: {u'dzfile[1]': [<InMemoryUploadedFile: image2.jpg (image/jpeg)>], u'dzfile[2]': [<InMemoryUploadedFile: image3.jpg (image/jpeg)>], u'dzfile[0]': [<InMemoryUploadedFile: image1.jpg (image/jpeg)>]}>
To access the actual files you need to get each key by it's name.
files = [request.FILES.get('dzfile[%d]' % i)
for i in range(0, len(request.FILES))]
NOW you have the file list you wanted. Simply iterate through it and create your objects however you want. I'm not sure on how your Models work so I'm going to approximate.
for f in files:
# Create a ClientUpload object by setting its FK to client and
# FileField to the file. Correct me if I deduced the models incorrectly
client_upload = ClientUpload.objects.create(
client=current_client,
file_upload=f,
)
That should be enough to create the objects that you want.
Dropzone Javascript
It seems that in the Click event listener you add to the submit button you have to add
e.preventDefault();
e.stopPropagation();
before calling processQueue() to avoid a double form submission.
As to the sendingmultiple, successmultiple and errormultiple, what do you want to happen there? The comments are just there to indicate when those events are trigered.
I personally use:
this.on('sendingmultiple', function () {
// `sendingmultiple` to hide the submit button
$('#my-dropzone').find('button[type=submit]').hide();
});
this.on('successmultiple', function (files, response) {
// `successmultiple` to reload the page (and show the updated info)
window.location.reload();
});
this.on('errormultiple', function (files, response) {
// `errormultiple` to un-hide the button
$('#my-dropzone').find('button[type=submit]').show();
});
But of course you can do what you want.
And finally, what do you intend to happen with that last line in the <script> tag? I don't quite understand it, it looks like if you wanted to re-process the queue on success. It seems not to belong there.
Comment if anything's off, but this setup works fine for me.
In your Javascript, I think you want to use this for the paramName:
paramName: "file_upload",
in order for a Django Form or ModelForm to recognize the uploaded files.
Also make sure that the upload request is using a multipart/form-data content type.
Also, try this instead of "get_list":
dz_files = request.FILES.getlist("file_upload")
I don't know if what i show now will help you specifically but maybe it will help others,Working with dropzone made me do a workaround because ajax, files and django combined are always a little complicated.
so in my html i have this code:
<div class="logos">
<i class="fa fa-upload" id="dropzone_icon" data-name="icon" title="{% trans "Drag and drop or click" %}" alt="{% trans "Drag and drop or click" %}" ></i>
<input type="hidden" name="icon" value="" >
<input type="hidden" name="icon_name" value="" >
<div class="img-holder">
<img title='{% trans "Upload a Company Icon" %}' id="img_icon" alt='{% trans "Company icon" %}' src="{* icon *}"/>
</div>
<label>{% trans "Company Icon" %}</label>
</div>
in my js i got this:
dropz = new Dropzone(value, {
url: "branding/dropzone",
maxFiles: 1,
acceptedFiles: "image/*",
thumbnail: function(file, dataUrl) {
/* change existing image */
var file_type = file.name.split('.');
file_type = file_type[file_type.length - 1];
if(!(file_type=="png" || file_type=="jpg" || file_type=="jpeg")){
createAlert('file type must be .png, .jpg or .jpeg', '#pp_content', 'alert');
return false;
}
$("input[name='icon']").val(dataUrl.split(",")[1]);
$("input[name='icon_name']").val(file.name);
$("#img_" + type).prop("src", dataUrl);
this.removeFile(file);
},
previewTemplate: "<span></span>",
autoProcessQueue: false
});
this tells dropzone to insert into the values into the inputs(the base64 presentation of the image, and the file name) so basically i'm sending the image as a string.
after sending the inputs as a form in the ajax, this is how i handle them in my views.py:
import datetime
from django.core.files.base import ContentFile
def base64_to_image(img_b64,img_name):
"""
Creates image file from bas64 encoded data
:param img_b64: base64 data
:param img_name: filename for created image
:return: file or false if there's no data
"""
if img_b64:
image_data = b64decode(img_b64)
img_file = ContentFile(image_data,datetime.datetime.now().strftime("%y%d%m_%H%M%S") + img_name)
return img_file
else:
return False
company.icon = base64_to_image(request.POST["icon"], request.POST["icon_name"])
company.save()
this is my work around working with dropzone, maybe it will help others here as well
This question already has answers here:
How to save an HTML5 Canvas as an image on a server?
(8 answers)
Closed 8 years ago.
I m creating product design page for e-commerce web site...
I need to save designed image from client side to database....
I tried to save but it could'nt save...and html5 canvas is new for me...
My html code..
...................
<div id="clothing-designer">
<div class="fpd-product" title="Shirt Front" data-thumbnail="images/yellow_shirt/front/preview.png">
<img src="./images/yellow_shirt/front/base.png" title="Base Front" data-parameters='{"x": 123, "y": 81, "colors": "#d59211", "price": 20}' />
<img src="./images/yellow_shirt/front/body.png" title="Hightlights" data-parameters='{"x": 249, "y": 80}' />
<img src="./images/yellow_shirt/front/shadows.png" title="Shadow" data-parameters='{"x": 123, "y": 81}' />
<span title="Any Text" data-parameters='{"x": 243, "y": 181, "removable": true, "draggable": true, "rotatable": true, "resizable": true, "colors": "#000000"}'>Default Text</span>
<div class="fpd-product" title="Shirt Back" data-thumbnail="images/yellow_shirt/back/preview.png">
<img src="./images/yellow_shirt/back/base.png" title="Base Back" data-parameters='{"x": 123, "y": 81, "colors": "#d59211", "price": 20}' />
<img src="./images/yellow_shirt/back/body.png" title="Hightlights" data-parameters='{"x": 277, "y": 79}' />
<img src="./images/yellow_shirt/back/shadows.png" title="Shadow" data-parameters='{"x": 123, "y": 81}' />
</div>
</div>
You give little info, but here is a brief overview of the process you will need.
A full description of how to get design info from the client to your database is beyond the scope of a Stackoverflow discussion, but this example should get you started with the concepts involved.
Convert the canvas to an imageUrl
If you want to save the canvas content as an image you can use canvas.toDataURL() which returns a DataURL of the canvas in .png format. For example:
var canvas=document.getElementById("myCanvas");
var dataUrl=canvas.toDataURL();
Send that dataUrl back to your server with an AJAX post
$.ajax({
type: "POST",
url: "http://localhost/saveCanvasDataUrl.php",
data: {image: dataUrl}
})
.done(function(respond){console.log("done: "+respond);})
.fail(function(respond){console.log("fail");})
.always(function(respond){console.log("always");})
On the PHP side, save the incoming dataURL to a database:
<?php
if(!isset($_POST["code"])){
die("Post was empty.");
}
$sql="insert into designs(image) values(:image)";
// INSERT with named parameters
$conn = new PDO('mysql:host=localhost;dbname=myDB', "root", "myPassword");
$stmt = $conn->prepare($sql);
$stmt->bindValue(":image",$_POST["image"]);
$stmt->execute();
$affected_rows = $stmt->rowCount();
echo $affected_rows;
?>
Alternatively...
With this all said, it might be more useful to save the components of the design that the user created rather than an image of that design.
Create a javascript object containing the specific info about the design:
var item1={
product:"shirt",
color:"#d59211",
price:20,
text:"Default Text",
textX:243,
textY:181
}
Use JSON to convert that object into a string
var item1Json=JSON.stringify(item1);
Then post that useful design data to your database instead of the image.
You can use HTML5 Canvas' toDataURL() which according to the docs:
Returns a data: URL containing a representation of the image in the format specified by type (defaults to PNG)
It is used like this:
var canvas = document.getElementById('thecanvaselement');
// ...maybe some more canvas drawing operations here
var url = canvas.toDataURL();
The results (stored in the url variable) can then be sent back to the server using AJAX and then saved to your database like you would normally do.