Uploading multiple images using Protractor - javascript

I have a scenario in my test suite, where I need to
Click on a button.
Upload an image from a specified directory.
Wait for 15 seconds
Repeat Steps 1-3 for all the images in the specified directory.
How can I achieve this - uploading an array of images, or a group of images, in specified folder, one by one. The test also includes the check that an image should not have been uploaded before.
I am able to upload a single file using the code below -
var fileUpload = 'path_to_file';
absolutePath = path.resolve(__dirname,fileUpload);
console.log(absolutePath);
this.file_Upload2.sendKeys(absolutePath);
browser.actions().sendKeys(protractor.Key.ENTER).perform();
browser.sleep(20000);
Please note that there is only a single button for uploading the images and it remains constant.

If you change your fileUpload variable to point to the directory where the files are held, rather than the file itself, you can just loop over everything in the directory. Something like this:
var fileUpload = 'path_to_directory';
var file_Upload2 = this.file_Upload2;
var absolutePath = path.resolve(__dirname, fileUpload);
fs.readdir(absolutePath, (err, files) => {
for (i = 0; i < files.length; i++) {
var fullPath = path.resolve(absolutePath, files[i]);
file_Upload2.clear().sendKeys(fullPath);
browser.actions().sendKeys(protractor.Key.ENTER).perform();
browser.sleep(20000);
}
});

Related

How to download multiple image files in .zip folder using JSZip in Vue.js

I am using Vue.js in a current project of mine and in that I need a feature, which will help any user to download pics that are available in the gallery.
There is an option that the user can select multiple images by clicking on the checkbox besides every image and to download the user needs to click a button to download all the pics that the user may have selected. The download will compress all the selected images to a zip folder and then the downloading stars and the user gets a final zip folder of all of the images that were selected.
To deliver this feature I have tried many Vue.js libraries but only JSZip was able to work for some extend. JSZip packed the images to a .zip and then downloads the zip folder but the images that are being packed, the type:"image/?" is also present but when one will open the file to see the image , then it gives an error of:
not an image of the defined type
in the image viewer. Here is the sample of the code that I have used:
export default {
methods: {
download_btn() {
var zip = new JSZip()
var img = zip.folder("images")
for (i = 0; i < this.image.length; i++) {
img.file("img.png", this.image[i].imageurl)
}
zip.generateAsync({
type: "blob"
}).then(function(content) {
saveAs(content, "img_archive.zip")
})
}
}
}
This code only saves one picture in the zip folder and also you can't open the image file.
Have a look at this one. Maybe it will help.
https://jsfiddle.net/jaitsujin/zrdgsjht/
You can manage zip folder structure by modifying this line
filename = filename.replace(/[\/\*\|\:\<\>\?\"\\]/gi, '').replace("httpsi.imgur.com","");
According to https://stuk.github.io/jszip/documentation/api_jszip/file_data.html the file method expects the image data as the second param to the call. It looks like you are passing the url of the image instead of the actual image bytes. If you refer to the docs you will see they retrieve the image via an ajax call.
To save more than one image, try using the number in the filename. And you'll have to use the image data, not the url, just like Deadron said.
In the docs they use xhr within a promise, see https://stuk.github.io/jszip/documentation/examples/downloader.html
Instead of:
for (i = 0; i < this.image.length; i++) {
img.file("img.png", this.image[i].imageurl)
}
Try:
for (i = 0; i < this.image.length; i++) {
img.file("img" + i + ".png", /* image data */)
}

Removing large files from file upload

I would like to allow a user to upload multiple files through Ajax. If some of the files are too large I would like to remove them from the upload list. How can I go about doing this? I currently have the following for my input field.
<input id="file" type="file" onChange={this.handleChange.bind(this)} required multiple />
So far I have come up with something like this to verify which files are too large:
handleChange(event) {
const target = event.target;
if (target.type === 'file'){
console.log("FILES")
const files = target.files
console.log("The following files are too large")
for (let i=0; i < files.length; i++){
if (files[i].size > 50000){
console.log(files[i].name)
}
}
}
}
The thing I am confused about is how files are handled, as they are not really links to the actual files on the file system. How does the file structure work? How can I store the good files into a new file structure that is uploadable with Ajax?
target.files is just an array. You can simple filter it, removing the files you don't want and do whatever you want with the new array (e.g. store it in the component's state).
const files = target.files.filter(file => file.size <= 50000);
this.setState({files});
// or uploadFiles(files)
If you are asking how to actually send files via an XMLHTTPRequest, this can be done with FormData:
const data = new FormData();
files.forEach(file => data.append(file.name, file));
and then send the FormData object via the XMLHTTPRequest.

How is a file split / chunked? How do I access the chunks sequentially?

For example, if I have an image and I download it -- how does the computer know that all the bytes are supposed to be in that sequential order?
When I upload an image, is it possible to upload it in "chunks" so I can access/use whatever I have uploaded thus far (i.e. I have only uploaded the top half of the image) -- how would I access it?
The same would go for video or PDF, etc.
You can read file into chunks and upload file in chunks.
See the example below.
<input type="file" name="filebrowsefileid">
var filePicker = document.getElementById('filebrowsefileid');
var file = filePicker.files[0];
var chunck = file.slice(a,b);
var reader = new FileReader();
reader.readAsBinaryString(chunck );
....
reader["onloadend"] = function () {
reader.result; // This is what you want
}

What order are files added to the DataTransfer FileList when dragging and dropping files in javascript?

I'm building a web application where users drag images into the browser and drop them to upload them. The problem is, I would like the files to upload in the same order as the folder they dragged them from. It seems like the files in the ondrop event's DragEvent.DataTransfer.FileList are sequenced randomly. How is this order determined? Is it possible for me to determine the original order of the files in the folder the user dragged them from?
After testing it a bit more I found the answer. The files are in the same order as the folder, but are offset to start with the actual individual file that you dragged in. So, if you highlight 5 files and drag them in by clicking on the third file and dragging, the order will be file 3, file 4, file 5, file 1, file 2. As for my second question, it would seem that finding the proper order would be contingent upon knowing the offset of the file dragged in. I haven't found a way to determine this yet.
Created a codepen to look into this further, using promises, as recommended, to handle nested directory structures:
function getFilesDataTransferItems(dataTransferItems) {
function traverseFileTreePromise(item, path = "", folder) {
return new Promise(resolve => {
if (item.isFile) {
item.file(file => {
file.filepath = path || "" + file.name; //save full path
folder.push(file);
resolve(file);
});
} else if (item.isDirectory) {
let dirReader = item.createReader();
dirReader.readEntries(entries => {
let entriesPromises = [];
subfolder = [];
folder.push({name: item.name, subfolder: subfolder});
for (let entr of entries)
entriesPromises.push(
traverseFileTreePromise(entr, path || "" + item.name + "/", subfolder)
);
resolve(Promise.all(entriesPromises));
});
}
});
}
let files = [];
return new Promise((resolve, reject) => {
let entriesPromises = [];
for (let it of dataTransferItems)
entriesPromises.push(
traverseFileTreePromise(it.webkitGetAsEntry(), null, files)
);
Promise.all(entriesPromises).then(entries => {
resolve(files);
});
});
}
As Andrew points out, when a group of selected files is imported via drag and drop and dataTransfer, the files are reordered with the file that is dragged first and then wrapping to the actual first file. Confirmed this in Chrome and Firefox.
It gets even more complicated with nested directories. The order of files in a subdirectory is lost and the files are placed in alphabetical order with same level subdirectories last.
I'm afraid these are current limitations of the dataTransfer object as an experimental technology.

Using req.files for multiple uploads

So i am handling a multiple file upload on my client side, where my html looks like the following
form(method='post', enctype='multipart/form-data')#createReportForm
input(type='file', multiple='multiple', accept='image/png, image/gif, image/jpeg, image/jpg', name='uploadImages', data-max-size='5000000')#uploadFile
Now on my server side to access the contents of the file and other info i am using
req.files.uploadImages. This works fine if one file attached, but when multiple files are attached on the client this object only reads the last attached file and not the first one
Whats the reasoning behind this? Shouldn't req.files.uploadImages have info about both the files?
If multiple files are selected the req.files.uploadImages would hold all the files.
You can just loop over them:
var files = [].concat(req.files.uploadImages);
for(var x = 0; x < files.length; x++){
// upload file
}

Categories

Resources