I'm having troubles uploading doc and docx files, because I can't get the right type of file when converting it to base64. This is my input:
<input
accept=".pdf,.txt,.doc,.docx"
type="file"
(change)="onNativeInputFileSelect($event)"
#inputFile
hidden
/>
In my method I do this:
onNativeInputFileSelect(event) {
if (event.target.value) {
const file: File = event.target.files[0];
this.changeFile(file).then((base64: string): any => {
this.attachment.content= base64;
this.uploadFile(this.attachment);
});
}
}
then in "uploadFile" I send the file to server as base 64 string.
The changeFile methods is this:
changeFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
}
This works fine for pdf or txt files, but when I upload .doc or .docx files I get this base64 string:
data:application/octet-stream;base64,0M8R4KGxGuEAA[...]
while for pdf I correctly have:
data:application/pdf;base64,JVBERi0xLjQKJeLjz9MKMS
This means that when I try to download the file I don't get the correct type, because I have application/octet-stream, and so I can't put the right extension to the file.
I've tried by passing to the accept property of input component this:
application/msword,application/pdf,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document
But nothing changed and the Window's file chooser suggested me only .pdf and .txt files
EDIT
This is a working stackblitz
I get "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,UEsDBB[...]" for docx and "data:application/msword;base64,0M8R4KGxGuv[...]" for doc file.
Related
I'm able to upload a single using Webdriverio. But there are no options to upload multiple files from a single folder. Also I did tried searching for help on internet. There seems to be no discussions or topics to help. Please suggest how to upload multiple files from single folder using WebdriverIo.
Thanks!
The question here is: how multiple files are stored into input file tag in a HTML page?
HTML example:
<input type="file" id="test-file" name="input-file" multiple>
This function should be useful for single or multiple file, even for hidden or not displayed input:
const uploadFiles = async (filesPath, selector) => {
const files = Array.isArray(filesPath) ? filesPath : [filesPath];
const el = await $(selector);
await browser.execute((el) => el.style.display = 'block', el);
await el.waitForDisplayed();
await el.addValue(files.join('\n'));
}
await uploadFiles(['Users/username/etc.jpg', 'Users/username/etc.jpg'], '#test-file')
That's it.
I'm practicing building a Hybrid Mobile app with Quasar, Vue and Vuex.
I've successfully added my form input fields to my Vuex store but I don't know how to upload a file, in this case a photo, within my Form.
Here is my q-file input from my form, with the data.
<q-file
v-model="mealToSubmit.photo"
label="Upload File"
outlined
>
Data:
data () {
return {
mealToSubmit: {
name: '',
description: '',
photo: null,
grams: '',
calories: '',
visible: false
}
}
}
After I fill in the Form and click Save, all of the data appears on the page except for the photo I selected. In the console I get a 404 error:
404 http://localhost:8080/img/null 404 (Not Found)
I can see the problem here is that it's displaying null, instead of the name of the photo I upload, which is why I'm getting a 404 error.
Here are two screenshots, one of me filling in the Form and second is the data being displayed properly except for the photo, with the error message in the console.
NOTE:
Just to add to this, I've uploaded files before using Vue js and Bootstrap-Vue. I add an #change event on the File input with a v-model like this:
<b-form-group label="Upload Profile Photo (optional)" label-for="photo_id">
<b-form-file
v-model="profileData.photo_id"
id="photo_id"
placeholder="Choose a file..."
#change="attachImage"
accept=".jpg, .jpeg, .png"
></b-form-file>
</b-form-group>
Than in the Methods{}:
methods: {
attachImage(evt) {
const file = evt.target.files[0];
let reader = new FileReader();
reader.addEventListener('load', function() {
}.bind(this), false);
reader.readAsDataURL(file);
},
}
And then I bind the data using FormData(); and send it to the backend. This approach isn't working with the Quasar file upload input and the code that I have above.
I got it now:
<q-file
#input="getFile"
label="Upload file"
/>
methods: {
getFile(file) {
// file is in the file variable
this.mealToSubmit.photo = file
}
}
It works on Edge, Chrome, Firefox, but not in safari. In Safari the iframe looks like it knows it should display a pdf (grey background) but with no pages inside it.
const pdf = new Blob([new Uint8Array(arrayBuffer)], { type: 'application/pdf' })
setDataStreamURL(window.URL.createObjectURL(pdf))
...
<iframe title={iframeTitle} className={className} src={dataStreamURL} type={type} />
It does work fine if I give it an url to a pdf like this one:
https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf
but I need to give it the blob:... url created by window.URL.createObjectURL(pdf)
I might be a little late in answering this but I faced this same issue while previewing a PDF from a blob url using an iframe on Safari. FileReader did the trick for me. From your code, instead of using window.URL.createObjectURL(pdf), read the blob which is here is pdf through a FileReader as shown bellow:
const pdf = new Blob([new Uint8Array(arrayBuffer)], { type: 'application/pdf' })
const reader = new FileReader();
reader.onload = () => {
const url = reader.result; // Use this `url` in iframe src
};
reader.readAsDataURL(pdf);
Note that this trick worked in Safari but might not work in other browsers, so use the blob url for other browsers and this trick for Safari.
I use Selenium to test web app behaviour on file upload page.
The goal of test is to check application validations on file selection.
I use webDriver.SendKeys (C#) on file input to simulate file upload, file is selected successfully, but fileInput.files[0].size (js) is always 0 (or undefined?) and app shows error "Do not upload empty files". File size is correct on manual testing.
Any suggestions, on how to solve the problem?
UPDATE Code details:
HTML
<input id="file-path" type="file" data-bind="attr: { accept: mimeTypes }, event: { change: onFileSelect }" />
<small id="file-path-error" class="field-validation-error" data-bind="validationMessage: file"></small>
JS (file edit model uses knockout)
this.file = ko.observable().extend({
validation: [
{
validator: function(file) {
// valid if no file or file size < 5Mb
return !file || file.size < 5242880;
},
message: 'File size should be less than 5Mb'
}, {
validator: function(file) {
// valid if no file or file size > 0
return !file || file.size > 0;
},
message: 'Do not upload empty files'
}
]
});
this.onFileSelect = function(model, event) {
var fileInput;
fileInput = event.target;
if ((fileInput.files != null) && fileInput.files.length > 0) {
_this.file(fileInput.files[0]);
} else {
_this.file(null);
}
};
C#
webDriver.FindElement(By.Id("file-path")).SendKeys("C:\testFile.txt");
Assert.AreEqual(webDriver.FindElement(By.Id("file-path-error").Text,"");
Assertion always fails because file-path-error contains "Do not upload empty files" - that is the problem.
I was misleaded by answers on How to automate file upload in Internet Explorer using Selenium?
Discusstion on How to set a value to a file input in HTML? says that actually we can not upload files programmatically.
So there was no sence in expecting decent behaviour for such test.
I am using wicked_pdf plug-in for generating pdf. I am showing message and spinner when user click on pdf link and i want to hide that when pdf is generated and pushed to browser for download/show. I have added jquery code on body onload which will not execute. Is there any other way to trigger jquery function when pdf file pushed to browser?
This is a rather complicated issue, but can be solved nicely if you are willing to use jQuery plugins. http://jqueryfiledownload.apphb.com/ is a plugin that can do exactly what you need if I understood you correctly.
My frontend code looks like this
$.fileDownload('/Content/Print', {
successCallback: function (url) {
$("#PrintingMessage").dialog('close');
},
failCallback: function (responseHtml, url) {
$("#PrintingMessage").dialog('close');
if (responseHtml.indexOf('Error403') != -1) {
$("#PrintingFailedMessage").html("Error 403.");
} else if (responseHtml.indexOf('Error500') != -1) {
$("#PrintingFailedMessage").html("Error 500.");
}
$("#PrintingFailedMessage").dialog({ modal: true });
},
httpMethod: "POST",
data: $('#PublishForm').serialize()
});
And my backend does this at the end of the process. You'll have to translate that yourself :)
Response.SetCookie(new System.Web.HttpCookie("fileDownload", "true") { Path = "/" });
return File(file, System.Net.Mime.MediaTypeNames.Application.Octet, filename);