Query Regarding File Upload - javascript

I am using "File Upload" control and C# coding (backend) for uploading files(.jpeg/.png/.pdf) in my web application.
The files uploaded through this control should be saved in the server.
Everything is working fine but the problem i am facing is when a file type of xlsx or doc is been saved and the extension of that file is changed to .png or .jpeg and is being uploaded it is being uploaded into the server without any error.
While I am trying to open that image or pdf file in server it is as usually showing the error message the file cant be opened.
I have done extension validation but it does not show any effect here in this case.
Can anyone help me to get rid of this problem.(Either C# coding or Jquery Or javascript will do)

Here is how finally able to get the validation as I need using "Header codes":
System.IO.BinaryReader r = new System.IO.BinaryReader(FileUpload1.PostedFile.InputStream);
string fileclass = "";
byte buffer;
try
{
buffer = r.ReadByte();
fileclass = buffer.ToString();
buffer = r.ReadByte();
fileclass += buffer.ToString();
}
catch
{
}
r.Close();
if (fileclass != "3780" || fileclass != "255216" || fileclass != "13780") /*Header codes (3780-PDF);(255216-JPG,JPEG);(13780-PNG)*/
{
/*Your code goes here(things to do with the file uploaded)*/
}
For getting values for other file formats try uploading the file and set break point and get the header code.

Can you show us how your validation looks like ?!
There is two way to check the extension of a file that you are uploading. It should be like this following :
//In your aspx file :
<asp:FileUpload ID="FileUploadControl" runat="server"/>
<asp:Button runat="server" id="Btn_Upload" text="Upload" onclick="Btn_Upload_Click" />
//In your aspx.cs file :
// First soluce
protected void Btn_Upload_Click(object sender, EventArgs e)
{
if (FileUploadControl.PostedFile.ContentType != "application/pdf")
{
//Not an PDF
}
}
// Second soluce :
protected void Btn_Upload_Click(object sender, EventArgs e)
{
string extension = Path.GetExtension(FileUploadControl.PostedFile.FileName);
if (extension != ".pdf")
{
//Not an PDF
}
}
Of course, on these code sample you can add for exception for JPEG / PNG / ...

Edit, Updated
But my problem is the extension is a proper one which i need to upload
but the file type is not i mean an excel sheet can be saved with
extension jpeg
You can use FileReader, .readAsBinaryString() to check for file headers; e.g, JFIF for .jpeg, .jpg; PNG for .png; PDF for .pdf; RegExp.prototype.test() with RegExp /JFIF|PNG|PDF/
Use accept attribute at <input type="file"> element with value set to ".jpeg,.jpg, .png,.pdf" to exclude files with extensions other than .jpeg, .jpg, .png or .pdf from being able to be selected by user at Choose File dialog.
document.querySelector("input[type=file]")
.addEventListener("change", function(e) {
console.log(e.target.files[0].type);
var reader = new FileReader();
reader.onload = function(event) {
console.log(event.target.result
, /JFIF|PNG|PDF/.test(event.target.result))
}
reader.readAsBinaryString(e.target.files[0])
})
<input type="file" accept=".jpeg,.jpg,.png,.pdf" />

There are many image format, like webp for example why not support them all?
You can convert them client side before you upload them using canvas...
function convertImage(image, mimetype, quality) {
return new Promise(function(resolve){
var canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
canvas.getContext("2d").drawImage(image, 0, 0)
canvas.toBlob(resolve, mimetype, quality)
})
}
if(input.files[0].type === 'application/pdf') {
// upload directly (not a image)
} else {
var img = new Image
img.onerror = function() { /* not an image */}
img.onload = function() {
convertImage(img, 'image/png', 1).then(function(blob){
// upload the converted image
fetch('upload', {method: 'POST', body: blob})
})
}
img.src = URL.createObjectURL(input.files[0])
}
then you use this to help filter out the accepted files you want
<input type="file" accept="application/pdf, image/*">

Related

Creating new blob from older one that is stored in local storage

I have basic html page where I want to upload image file, and after closing or reloading page I want that image to be there.
HTML code is :
<input type='file' accept="image/*">
<img alt="your image" height=400 width=auto>
Javascript code:
let img = document.querySelector('img');
document.body.onload = () => {
if(localStorage.image){
let source = JSON.parse(localStorage.image)
let file = new File([source], 'download.jpg', {type: 'image/jpeg', lastModified: Date.now()})
img.src = URL.createObjectURL(file)
}
}
document.querySelector('input[type="file"]').addEventListener('change', function() {
img.src = URL.createObjectURL(this.files[0])
localStorage.image = JSON.stringify(img.src)
});
My questions are:
When I console.log(localStorage.image), after uploading and reloading page, I will get one blob, and because from security reasons I can't use same blob, I tried to make new File and then from that file to create blob that I can later use, but when I console.log new blob (conosle.log(img.src)) I received different blob, so my question is why that happened, is there a way to correct that, I see that these two files has different file.size but when I want to change that it stays same
Also is there a second way to do that
As you can't persist blob objects between sessions (the blob URL will expire), you need to use a serializable format such as a data URL. Using a FileReader you can read the image file straight to a data url, and this can be stored in localStorage.
const fileReader = new FileReader();
fileReader.addEventListener('loadend', function() {
img.src = fileReader.result;
storage['image'] = fileReader.result;
})
document.querySelector('input[type="file"]').addEventListener('change', function() {
if (this.files.length > 0) {
fileReader.readAsDataURL(this.files[0]);
}
});
Here is a pen where I modified your code to use FileReader and data URLs (had to use sessionStorage because of codepen but localStorage should work)
https://codepen.io/Douile/pen/gOwORea?editors=1011

How to upload a .mp3 file in HTML / Javascript and send to Java backend

We're trying to upload a song (.mp3) file from a JSP frontend written in HTML / Javascript. We need to upload to our Java backend using websockets. Does anyone have any suggestions on how we would could go about doing this?
Currently we are doing something like this on our JSP file:
<h1>Please Choose a Song file</h1>
<form name = "JSONUploadForm">
<input type = "file" name="file" accept = ".mp3"/> <br/>
<input type = "button" value = "Click to upload!" name = "button" onClick = "submitSong();"/>
</form>
Then we have our javascript function submitSong()
function submitSong(){
var songStuffs = document.getElementById("file");
console.log(songStuffs); --> we get "null" here
sendMessage(songStuffs);
alert("song sent");
}
function sendMessage(val, string) {
socket.send(string);
return false;
}
Also, here is our connect to server function. However, this functions correctly.
function connectToServer() {
socket = new
WebSocket("ws://localhost:8080/Project/socket");
socket.onopen = function(event) {
console.log("connected!");
}
You can also see our server side (.java file):
#OnMessage
public void onMessage(String message, Session session) throws IOException, EncodeException {
FileWriter fw = new FileWriter(new File(songName + ".mp3"));
fw.write(song);
BufferedReader fr = new BufferedReader(new FileReader(songName + ".mp3"));
String data = fr.readLine();
System.out.println("Song: " + data); --> Here we get "song: null"
}
Any suggestions would be greatly appreciated!
In your code you have an error
"var songStuffs = document.getElementById("file");"
Your file input without id.
this will work "var songStuffs = document.querySelector("[name=file]");"
I prefer using querySelector, because it mo flexeble and works exactly like jquery query selectors)))
You do not need any form, for upload files.
Please read this article https://www.html5rocks.com/en/tutorials/websockets/basics/,
it will be useful for you (search words "blob" at the page)
Html
<input id="file" type = "file" name="file" accept = ".mp3"/>
Code
var fileInput = document.querySelector("#file");
fileInput.addEventListener("change",function(){
connection.send(fileInput.files[0]);
});
If you need to send file and fields, you have 3 variants
create JSON {"field1":"value1","field2":"value1",
"file":"base64"}
manualy create formdata and parse form data at the
server with some webform stuff (example
https://stackoverflow.com/a/47279216/5138198)
Firstly send JSON
data, secondly send a file
Try with this, If you have to upload file you should add enctype in form.
<form enctype="multipart/form-data">
<input type = "file" name="file" id="song" accept = ".mp3"/>
</form>
Update:
You can use simply WebSocketFileTransfer plugin to send your file. This plugin helps in with many features like Auth, progress status, file/blob compatibility.
var songStuffs = document.getElementById("song").files[0];
var transfer = new WebSocketFileTransfer({
url: 'ws://ip:port/path/to/upload_web_socket_server',
file: songStuffs,
progress: function(event) {
// Update the progress bar
},
success: function(event) {
// Do something
}
});
transfer.start();

How to get the file object on success callback of cordova camera?

Currently I am using the following approach where it is giving details of file but not the actual object it seems like one we get from in javascript/jQuery. Does any one having the clue how to get the file object from File URI /native URI from mobile ios/android filesystem using cordova and javascript?
Below is the snippet I am using currently..
window.resolveLocalFileSystemURL(
filepath,
function(fileEntry) {
fileEntry.file(
function(file) {
var reader = new FileReader();
reader.onloadend = function() {
var imgBlob = new Blob([this.result], {type: "image/jpeg"});
var uploadedFile = imgBlob;
uploadedFile.name = file.name;
alert("Importing Asset from Camera.. " + uploadedFile.name);
alert(uploadedFile.type);
alert(uploadedFile.size);
importAsset(uploadedFile);
};
reader.readAsArrayBuffer(file);
},
function(error) { alert("Error in fileEntry.file():" + error) })
},
function(error) { alert("Error in window.resolveLocalFileSystemURL():" + error) }
);
Note: FileTransfer.upload() will not work in my case.
Above snippet I am using after taking from Append image file to form data - Cordova/Angular after going through the existing Q&A from #SO
Base64 Image Upload will work both in iOS/Android as I have tried:
As for iOS There is only one way to show image is using base64 format.You can use cordova-camera-plugin to to generate base64 image and put on img tag of HTML.I have set the flag to get data in jpeg,base64 in camera plugin.
<img id="cardImg">
Store the base64 image in javascript variable as:
var imgdata=data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
Then Simply pass data to img tag of HTML as:
cardImg.src=imgdata;
Done!

Upload base64 image to .NET webservice and convert it there

I have a function that sends data through data:JSON.stringify(formdata)using POST to a remove .NET webservice. I have no problem this far. What I want to do it to add also add a another value to the formdata JSON that will hold a base64 image data and send it to the server, and there I will convert it back to a JPEG image.
How can I so that? I already have a preview function that created a preview, but also create a base64 image:
function previewFile() {
var preview = document.querySelector('.uploadimage');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
preview.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
I see many question people asking how to upload image to the server. I want to stay with the current configuration but just pass the base64 image data to the server as a string. I see many developers struggling with that, and most of them just engine up creating a form in javascript and submitting like that.
Here is a recent way I did this:
string base64 = base64string.Substring(base64string.IndexOf(',') + 1);
byte[] imageData = Convert.FromBase64String(base64);
Image img;
using (var ms = new MemoryStream(imageData, 0, imageData.Length)) {
img = Image.FromStream(ms, true);
You will need:
using System.Drawing;
OR to simply convert to a jpg, use this:
File.WriteAllBytes("image.jpeg", Convert.FromBase64String(base64));
For sending the data I use the following JS:
function sendImage() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.onload = function (e) {
$("#imgImage").attr("src", e.target.result); //show a preview
//send e.target.result as a string to your webservice
};
FR.readAsDataURL(this.files[0]);
}
}
I use this event to listen for uploaded files:
document.getElementById("fileid").addEventListener("change", sendImage, false);
And the front end:
<input type="file" id="fileid" />

Post multiple data such as image file thourh ajax to php

I have some trouble sending the following html input type to my php script through ajax. I'm guessing that I have to define the file in tje js code hoverver how to do so when I have more variables that are taking information from the same file (se php code)?
<input id="imagefile" class="file" type="file" name="image" />
through this code
$("#addmedia").click(function(ev) {
ev.preventDefault();
var p = $("#p").val();
var mediatype = $("#mediatype option:selected").val();
var addmediatype = $("#mediatype option:selected").val();
var title = $("#title").val();
var video = $("#medialink").val();
var imagefile = $("#imagefile").val();
$.post("lib/action.php", {
mediatype: mediatype,
addmediatype: addmediatype,
title: title,
video: video,
addmedia: true
}, function(data) {
$("#notify").hide().html("<h1>!</h1><h2>" + data + "</h2>").slideDown(500);
setTimeout(function() { $("#notify").slideUp(500) }, 2500);
});
});
so that it works with my php upload script.
In my php code i use following variables to get infro from the file
if( $_POST['p'] == 1 ) {
$name = $_FILES['image']['name'];
$temp = $_FILES['image']['tmp_name'];
$type = $_FILES['image']['type'];
$size = $_FILES['image']['size'];
(...)
}
When you use $().val for a file field, you're only getting the filename because of security restrictions.
One solution (for IE 10+, Chrome, FF) is to read the file contents using https://developer.mozilla.org/en-US/docs/Web/API/FileReader, base64 encode it and upload it. See Reading client side text file using Javascript
document.getElementById('file').addEventListener('change', readFile, false);
function readFile (evt) {
var files = evt.target.files;
var file = files[0];
var reader = new FileReader();
reader.onload = function() {
console.log(this.result);
}
reader.readAsText(file)
}
Note that there are too many gotchas when uploading files through AJAX and can't possibly address with a concise answer as StackOverflow answers should be.
The easiest workaround is to not send it using AJAX, use a regular form upload, but target a hidden iframe so your page doesn't reload.
See:
Sending binary data in javascript over HTTP
Multiupload with PHP/JavaScript
http://www.html5rocks.com/en/tutorials/file/xhr2/
http://blueimp.github.io/jQuery-File-Upload/

Categories