I don't get attachment upload for the browser to work.
Some hints are here, others there. The docs are quite good but I'm unable to translate that to a AJAX upload.
I'm looking for a super simple HTML/JavaScript example (with or w/o jQuery) of how to upload a file from (relatively modern) browser to the db without making use of jquery.couch.app.js wrapper or stuff. The simpler the besser.
Any help appreciated.
Alright, here's your pure JavaScript file upload implementation.
The basic algorithm is like this:
Get the file from the file input element
Get the file name and type off the file object
Get the latest document revision of the document you want to attach the file to
Attach the file to document using the fetched revision
The HTML part basically consists of a simple form with two elements, an input of type file and a button of type submit.
<form action="/" method="post" name="upload">
<input type="file" name="file" />
<button type="submit" name="submit">Upload</button>
</form>
Now to the JavaScript part.
window.onload = function() {
var app = function() {
var baseUrl = 'http://127.0.0.1:5984/playground/';
var fileInput = document.forms['upload'].elements['file'];
document.forms['upload'].onsubmit = function() {
uploadFile('foo', fileInput.files[0]);
return false;
};
var uploadFile = function(docName, file) {
var name = encodeURIComponent(file.name),
type = file.type,
fileReader = new FileReader(),
getRequest = new XMLHttpRequest(),
putRequest = new XMLHttpRequest();
getRequest.open('GET', baseUrl + encodeURIComponent(docName),
true);
getRequest.send();
getRequest.onreadystatechange = function(response) {
if (getRequest.readyState == 4 && getRequest.status == 200) {
var doc = JSON.parse(getRequest.responseText);
putRequest.open('PUT', baseUrl +
encodeURIComponent(docName) + '/' +
name + '?rev=' + doc._rev, true);
putRequest.setRequestHeader('Content-Type', type);
fileReader.readAsArrayBuffer(file);
fileReader.onload = function (readerEvent) {
putRequest.send(readerEvent.target.result);
};
putRequest.onreadystatechange = function(response) {
if (putRequest.readyState == 4) {
console.log(putRequest);
}
};
}
};
};
};
app();
};
Basically, I intercept the submit event of the form by binding my own function to the form's onsubmit event and returning false.
In that event handler I call my main function with two parameters. The first one being the document name and the second one being the file to upload.
In my uploadFile() function I set the file name, file type and grab some instances. The first HTTP request is a GET request to obtain the current revision of the document. If that request succeeds I prepare the PUT request (the actual upload request) by setting the previously obtained revision, the proper content type and then I convert the file to an ArrayBuffer. Once that's done I just send the HTTP request I've just prepared and then I relax.
The standalone attachment upload scheme looks like this:
PUT host/database/document/filename?revision=latest-revision
Of course using the proper content type in the HTTP request header.
Note: I'm well aware that I'm not making use of defensive programming here at all, I did that deliberately for brevity.
Related
I had created an Excel file at the backend (Express JS) using Exceljs npm module. I have it stored in a temp directory. Now I would want to send the file from the back-end to the front-end and download it there when the user clicks a button. I am struck on two things
1. How to send the file from the backend to the frontend through an HTTP POST request
2. How to then download the file in the front-end
Edited content:
I need the front end to be a button that appends the file to it and then download it. This is how my code looks, I am not getting the file properly from the backend to the front-end
front end file:
function(parm1,parm2,parm3){
let url =${path}?parmA=${parm1}&parmB=${parm2}&parmC=${parm3};
let serviceDetails = {};
serviceDetails["method"] = "GET";
serviceDetails["mode"] = "cors";
serviceDetails["headers"] = {
"Content-Type": "application/json"
};
fetch(url, serviceDetails)
.then(res => {
if (res.status != 200) {
return false;
}
var file = new Blob([res], { type : 'application/octet-stream' });
a = document.createElement('a'), file;
a.href = window.URL.createObjectURL(file);
a.target = "_blank";
a.download = "excel.xlsx";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}).catch(error => {
return false;
});
}`
router.js
var abc = ... // this is a object for the controller.js file
router.get('/path', function(req, res) {
abc.exportintoExcel(req, res);
});
controller.js
let xyz = ... //this is a object for the service.js file
exports.exportintoExcel = function(req, res) {
xyz.exportintoExcel(reqParam,res);
}
service.js
exportintoExcel(req,response){
//I have a excel file in my server root directory
const filepath = path.join(__dirname,'../../nav.txt');
response.sendFile(filepath);
})
}
This is a complete re-write of an earlier answer, so sorry if anyone needed that one, but this version is superior. I'm using a project created with express-generator and working in three files:
routes/index.js
views/index.ejs
public/javascripts/main.js
index.ejs
Start with an anchor tag that has the download attribute, with whatever filename you wish, and an empty href attribute. We will fill in the href in the main.js file with an ObjectURL that represents the Excel file later:
<body>
<a id="downloadExcelLink" download="excelFile.xlsx" href="#">Download Excel File</a>
<script type="text/javascript" src="/javascripts/main.js"></script>
</body>
public/javascripts/main.js
Select the anchor element, and then make a fetch() request to the route /downloadExcel. Convert the response to a Blob, then create an ObjectURL from this Blob. You can then set the href attribute of the anchor tag to this ObjectURL:
const downloadExcelLink = document.getElementById('downloadExcelLink');
(async () => {
const downloadExcelResponse = await fetch('/downloadExcel');
const downloadExcelBlob = await downloadExcelResponse.blob();
const downloadExcelObjectURL = URL.createObjectURL(downloadExcelBlob);
downloadExcelLink.href = downloadExcelObjectURL;
})();
routes/index.js
In the index router, you simply need to call the res.sendFile() function and pass it the path to the Excel file on your server.
router.get('/downloadExcel', (req, res, next) => {
const excelFilePath = path.join(__dirname, '../tmp/excel.xlsx');
res.sendFile(excelFilePath, (err) => {
if (err) console.log(err);
});
});
That's it! You can find a git repo here of the project. Clone into it and try it out for yourself if you can't get this code to work in your project as it is.
How It Works
When the page loads, 4 requests are fired off to our server, as we can see in the console output:
GET / 200 2.293 ms - 302
GET /stylesheets/style.css 200 1.123 ms - 111
GET /javascripts/main.js 200 1.024 ms - 345
GET /downloadExcel 200 2.395 ms - 4679
The first three requests are for index.ejs (/), the CSS stylesheet, and our main.js file. The fourth request is sent by our call to fetch('/downloadExcel') in the main.js file:
const downloadExcelResponse = await fetch('/downloadExcel');
I have a route-handler setup in routes/index.js at this route that uses res.sendFile() to send a file from our filesystem as the response:
router.get('/downloadExcel', (req, res, next) => {
const excelFilePath = path.join(__dirname, '../tmp/excel.xlsx');
res.sendFile(excelFilePath, (err) => {
if (err) console.log(err);
});
});
excelFilePath needs to be the path to the file on YOUR system. On my system, here is the layout of the router file and the Excel file:
/
/routes/index.js
/tmp/excel.xlsx
The response sent from our Express server is stored in downloadExcelResponse as the return value from the call to fetch() in the main.js file:
const downloadExcelResponse = await fetch('/downloadExcel');
downloadExcelResponse is a Response object, and for our purposes we want to turn it into a Blob object using the Response.blob() method:
const downloadExcelBlob = await downloadExcelResponse.blob();
Now that we have the Blob, we can call URL.convertObjectURL() to turn this Blob into something we can use as the href for our download link:
const downloadExcelObjectURL = URL.createObjectURL(downloadExcelBlob);
At this point, we have a URL that represents our Excel file in the browser, and we can point the href to this URL by adding it to the DOM element we selected earlier's href property:
When the page loads, we selected the anchor element with this line:
<a id="downloadExcelLink" download="excelFile.xlsx" href="#">Download Excel File</a>
So we add the URL to the href here, in the function that makes the fetch request:
downloadExcelLink.href = downloadExcelObjectURL;
You can check out the element in the browser and see that the href property has been changed by the time the page has loaded:
Notice, on my computer, the anchor tag is now:
<a id="downloadExcelLink" download="excelFile.xlsx" href="blob:http://localhost:3000/aa48374e-ebef-461a-96f5-d94dd6d2c383">Download Excel File</a>
Since the download attribute is present on the link, when the link is clicked, the browser will download whatever the href points to, which in our case is the URL to the Blob that represents the Excel document.
I pulled my information from these sources:
JavaScript.info - Blob as URL
Javascript.info - Fetch
Here's a gif of how the download process looks on my machine:
OK, now that I see your code, I can try and help out a little. I have refactored your example a little bit to make it easier for me to understand, but feel free to adjust to your needs.
index.html
I don't know what the page looks like that you're working with, but it looks like in your example you are creating an anchor element with JavaScript during the fetch() call. I'm just creating one with HTML in the actual page, is there a reason you can't do this?
<body>
<a id="downloadLink" download="excel.xlsx" href="#">Download Excel File</a>
<script type="text/javascript" src="/javascripts/test.js"></script>
</body
With that in hand, here is my version of your front end JS file:
test.js
const downloadLink = document.getElementById('downloadLink');
sendFetch('a', 'b', 'c');
function sendFetch(param1, param2, param3) {
const path = 'http://localhost:3000/excelTest';
const url = `${path}?parmA=${param1}&parmB=${param2}&parmC=${param3}`;
const serviceDetails = {};
serviceDetails.method = "GET";
serviceDetails.mode = "cors";
serviceDetails.headers = {
"Content-Type": "application/json"
};
fetch(url, serviceDetails).then((res) => {
if (res.status != 200) {
return false;
}
res.blob().then((excelBlob) => {
const excelBlobURL = URL.createObjectURL(excelBlob);
downloadLink.href = excelBlobURL;
});
}).catch((error) => {
return false;
});
}
I had to fill in some details because I can't tell what is going on from your code. Here are the things I changed:
Selected the DOM element instead of creating it:
Your version:
a = document.createElement('a'), file;
My version:
index.html
<a id="downloadLink" download="excel.xlsx" href="#">Download Excel File</a>
test.js
const downloadLink = document.getElementById('downloadLink');
This saves us the trouble of creating the element. Unless you need to do that for some reason, I wouldn't. I'm also not sure what that file is doing in your original.
Name the function and change parm -> param for arguments list
Your version:
function(parm1,parm2,parm3){
My version:
function sendFetch(param1, param2, param3) {
I wasn't sure how you were actually calling your function, so I named it. Also, parm isn't clear. Param isn't great either, should describe what it is, but I don't know from your code.
Create a path variable and enclose url assignment in backticks
Your version:
let url =${path}?parmA=${parm1}&parmB=${parm2}&parmC=${parm3};
My version:
const path = 'http://localhost:3000/excelTest';
const url = `${path}?parmA=${param1}&parmB=${param2}&parmC=${param3}`;
In your version, that url assignment should throw an error. It looks like you want to use string interpolation, but you need backticks for that, which I added. Also, I had to define a path variable, because I didn't see one in your code.
Cleaned up some formatting
I used 'dot' notation for the serviceDetails, but that was just personal preference. I also changed the spacing of the fetch() call, but no need to reprint that here. Shouldn't effect anything.
Create a blob from the fetch response
Your version:
var file = new Blob([res], { type : 'application/octet-stream' });
My version:
res.blob().then((excelBlob) => {
I'm not sure why you are calling the Blob constructor and what that [res] is supposed to be. The Response object returned from fetch() has a blob() method that returns a promise that resolves to a Blob with whatever MIME-type the data was in. In an Excel documents case, this is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
Create an ObjectURL from the Blob and add this URL to the href of the anchor tag.
Your version:
a = document.createElement('a'), file;
a.href = window.URL.createObjectURL(file);
a.target = "_blank";
a.download = "excel.xlsx";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
My version:
const excelBlobURL = URL.createObjectURL(excelBlob);
downloadLink.href = excelBlobURL;
You have to do a bunch of DOM manipulation, which I'm not sure why you need. If you do have to dynamically create this element, then I'm not sure why you are 'clicking' it, then removing it, if the user is supposed to be able to click it. Maybe clarify for me why you are doing this, or if you really need to do it. Either way, in my version I create the ObjectURL and then assign it, but you could just as easily not store it in a variable.
Call the function that sends the fetch request.
As my function signature is:
function sendFetch(param1, param2, param3)
I needed to call it somewhere in order to fire off the request, so I did so like this:
sendFetch('a', 'b', 'c');
Right when the page loads, as you can see from the server logs:
GET / 304 0.448 ms - -
GET /javascripts/test.js 304 1.281 ms - -
GET /excelTest?parmA=a&parmB=b&parmC=c 304 0.783 ms - -
The first two requests are for the index.html page and the test.js file, then the fetch request is fired with the param's I passed in. I'm not sure how you are doing this in your app, because that is not included in your code.
Everything I just covered is Front-End. I'm assuming your server-side code is actually sending an excel file with your call to response.sendFile() in service.js. If you are sure that the file is getting sent, then the code I've given you should work, when adjusted to your app.
So, in conclusion, what this code does is:
Load an HTML page with an anchor tag with no href attribute set.
Send off a fetch() request to the server.
Turn the fetch response into a Blob, then create an ObjectURL from this Blob.
Assign that ObjectURL to the anchor tag's href attribute.
When the user clicks the 'Download Excel File' link, the Excel sheet should be downloaded. If you didn't want them to see the link until after the fetch request, you could definitely do create the anchor tag in JS instead, let me know if you want to see how to do that.
As before, here is a gif showing how it looks on my machine (this is with your version and my modifications):
Edit, original question has been resolved as to why file was converted to string. The code has been edited to reflect these corrections. The API handler is now outputting object as data type and buffer as the value of request.payload.file.
I'm using Aurelia to make a Single Page App. There is a HTML form that accepts two input fields, one for a file, one for text. These fields are bound to variables (selecetdImage and title) in an associated TypeScript view model. In the viewmodel they are used as arguments in a function that appends them to formData and sends a http post request with the formData to an Node/js Hapi framework API handler.
When I console.log(typeof(selectedImage) in the Aurelia app, it states object, but when I console log typeOf(selecetdImage) in the handler, I get String. I'm guessing this is why my function isn't working and giving 500 error messages
The handler itself works. I used it in a MVC server based web app. In that context, HTML form triggers a post request, and the MVC handler successfully receives the file, writes it to local/temp.img and uploads it to cloudinary.
But with the API version, where I assembled the form data myself as above, the file isn't written to local/temp.img and the cloudinary upload fails.
Edit.
I changed the viewmodel variables to
title = null;
files = null;
and I changed the formData append function to:
formData.append('file', File, files[0]);
As per the example here. The code below is now modified to match this update.
Now when I console log the value of file in the API handler, the output is:
<Buffer ff d8 ff e0 00 10.......
I'm not sure what to do with this data. I assume it's the image binary data in octal? And if so, does anyone know how to write it as an image in node?
The payload is no longer of type string, now it's type object.
<form submit.delegate="uploadPhoto()" enctype="multipart/form-data">
<div class="two fields">
<div class="field">
<label>File</label>
<input type="file" name="file" accept="image/png, image/jpeg" files.bind="files">
</div>
<div class="field">
<label>Title</label> <input value.bind="title">
</div>
</div>
<button type="submit"> Upload </button>
</form>
//photoUpload.ts// (view model associated with above html
#inject(POIService)
export class PhotoForm {
#bindable
photos: Photo[];
title = null;
files = null;
constructor (private poi: POIService) {}
uploadPhoto() {
const result = this.poi.uploadPhoto(this.title, this.files);
console.log(this.title);
console.log(result);
}
//POIService (where contains injected function to create HTTP request
async uploadPhoto(title: string, files){
console.log("now uploading photo for: " + this.currentLocation)
let formData = new FormData();
formData.append("title", title);
formData.append("location", this.currentLocation); //don't worry about this variable, it's set by another function every time a page is viewed
formData.append("file", files[0]);
const response = await this.httpClient.post('/api/locations/' + this.currentLocation + '/photos', formData);
console.log(response);
}
//API Handler (accepts HTTP request, writes the image to a local folder, the uploads to cloudinary and returns the url and photo_id which are stored in a Mongod document
create: {
auth: false,
handler: async function(request, h) {
const photo = request.payload.file;
await writeFile('./public/temp.img', photo);
const result = await cloudinary.v2.uploader.upload('./public/temp.img', function(error, result) {
console.log(result)
});
const newPhoto = new Photo({
title: request.payload.title,
url: result.url,
public_id: result.public_id,
location: request.params.name
})
await newPhoto.save();
return newPhoto;
}
},
Is it a very long string, containing "data:b64" in the first 15 or so characters? If so, that means it's the base64 data.
In my front-end I use angular6 and I have this form where you can choose an image either by dropping a file in a div or clicking the div to open a file picker.
The form is
<form [formGroup]="imageUpload" (ngSubmit)="imageUploadSubmitted($event.target)" >
<div id="imageDrop" (click)='imageInput.click()' (drop)="drop($event)" (dragover)="allowDrop($event)" #imageDrop></div>
<input type="file" (change)='imageChange($event)' #imageInput id="imageInput" name = 'imageInput' accept=".png, .jpg, .jpeg, .gif" formControlName="imageInput" required >
<button type="submit" >Submit</button>
</form>
This is the typescript
selectedFile:File=null;
allowDrop(e) {
e.preventDefault();
}
drop(e) {
e.preventDefault();
this.imageUpload.controls.imageInput.reset();
this.selectedFile = e.dataTransfer.files[0];
let input = this.imageUpload.controls.imageInput as any;
input.value = e.dataTransfer.files[0];
}
imageChange(e){
this.selectedFile = e.target.files[0];
}
So, when dropping an image, get it from the event and put it in the file input. When the form is submitted, send the form data to a service for posting. The console.log shows a File object (__proto__ : File) whether you picked an image from the file picker, or dropped one in the div.
imageUploadSubmitted(form){
console.log('imageInput value - ', this.imageUpload.controls.imageInput.value);
this.mapcmsService.uploadImage(form).subscribe((data) =>{
if(data.success){ alert('all good'); }
else{ alert('error'); }
})
}
The service grabs the form controls and builds a FormData object to send in node.
uploadImage(data){
let formData = new FormData(data);
let headers = new Headers();
headers.append('Authorization',this.userToken);
return this.http.post('http://localhost:3000/user/upload/image', formData ,{headers:headers} ).pipe(map(res => res.json()));
}
In node I use formidable to get the file and save it. This is for testing.
var form = new formidable.IncomingForm();
form.parse(req);
form.on('file', function (name, file){
console.log('file' , file);
});
The problem is that if I have chose an image via the file picker, I get a file of type image/jpeg , a name a path and a size.
If I chose an image by drag and drop, I get a file of type application/octet-stream. This has no name and no size.
I would like to get image/jpeg in both cases. I am confused, is this a node or angular issue? How can I fix this ?
Thanks
angular 6 , node 8.11.1, formidable 1.2.1
The issue is that the assignment in the drop event does not actually set the value of the input because file inputs are not supported by Angular reactive forms. I am talking about this lines:
let input = this.imageUpload.controls.imageInput as any;
input.value = e.dataTransfer.files[0];
So when you drop in your case you are not actually sending the file to the server at all. That is why the data you get is wrong. Here are also links to two other stack overflow questions about reactive forms and file upload where there is more information regarding this issue.
How to include a file upload control in an Angular2 reactive form?
Using reactive form validation with input type=“file” for an Angular app
There are two possible solutions to workaround this issue. The first is that you get the ElementRef of the file input by using the ViewChild query. And then assign the files to the native html element directly. The good thing with this approach is that you will see the dropped file name also in the file input. The downside is that this might not work in all browsers. The official documentation on MDN says that it works in modern browsers but for me it did work in Chrome and not in Edge.
Here is a sample of the code:
#ViewChild('imageInput') private imageInput: ElementRef;
public drop(e: DragEvent) {
e.preventDefault();
this.imageUpload.controls.imageInput.reset();
this.selectedFile = e.dataTransfer.files[0];
this.imageInput.nativeElement.files = e.dataTransfer.files;
}
The other approach is that you build the FormData object yourself by adding the selected file yourself in code before sending it to the server. This should work anywhere without issues. Here is a sample code:
let formData = new FormData();
formData.append('imageInput', this.selectedFile);
I have created also a StackBlitz example where you can see all the code.
How can I set the value of this?
<input type="file" />
You cannot set it to a client side disk file system path, due to security reasons.
Imagine:
<form name="foo" method="post" enctype="multipart/form-data">
<input type="file" value="c:/passwords.txt">
</form>
<script>document.foo.submit();</script>
You don't want the websites you visit to be able to do this, do you? =)
You can only set it to a publicly accessible web resource as seen in this answer, but this is clearly not the same as a client side disk file system path and it's therefore useless in that context.
You can't.
The only way to set the value of a file input is by the user to select a file.
This is done for security reasons. Otherwise you would be able to create a JavaScript that automatically uploads a specific file from the client's computer.
Not an answer to your question (which others have answered), but if you want to have some edit functionality of an uploaded file field, what you probably want to do is:
show the current value of this field by just printing the filename or URL, a clickable link to download it, or if it's an image: just show it, possibly as thumbnail
the <input> tag to upload a new file
a checkbox that, when checked, deletes the currently uploaded file. note that there's no way to upload an 'empty' file, so you need something like this to clear out the field's value
You can't. And it's a security measure. Imagine if someone writes JS that sets file input value to some sensitive data file?
I have write full example for load URL to input file, and preview
you can check here
1
https://vulieumang.github.io/vuhocjs/file2input-input2file/
in short you can use this function
function loadURLToInputFiled(url){
getImgURL(url, (imgBlob)=>{
// Load img blob to input
// WIP: UTF8 character error
let fileName = 'hasFilename.jpg'
let file = new File([imgBlob], fileName,{type:"image/jpeg", lastModified:new Date().getTime()}, 'utf-8');
let container = new DataTransfer();
container.items.add(file);
document.querySelector('#file_input').files = container.files;
})
}
// xmlHTTP return blob respond
function getImgURL(url, callback){
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
As everyone else here has stated: You cannot upload just any file automatically with JavaScript.
HOWEVER! If you have access to the information you want to send in your code (i.e., not C:\passwords.txt), then you can upload it as a blob-type, and then treat it as a file.
What the server will end up seeing will be indistinguishable from someone actually setting the value of <input type="file" />. The trick, ultimately, is to begin a new XMLHttpRequest() with the server...
function uploadFile (data) {
// define data and connections
var blob = new Blob([JSON.stringify(data)]);
var url = URL.createObjectURL(blob);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myForm.php', true);
// define new form
var formData = new FormData();
formData.append('someUploadIdentifier', blob, 'someFileName.json');
// action after uploading happens
xhr.onload = function(e) {
console.log("File uploading completed!");
};
// do the uploading
console.log("File uploading started!");
xhr.send(formData);
}
// This data/text below is local to the JS script, so we are allowed to send it!
uploadFile({'hello!':'how are you?'});
So, what could you possibly use this for? I use it for uploading HTML5 canvas elements as jpg's. This saves the user the trouble of having to open a file input element, only to select the local, cached image that they just resized, modified, etc.. But it should work for any file type.
the subject is very old but I think someone can need this answer!
<input type="file" />
<script>
// Get a reference to our file input
const fileInput = document.querySelector('input[type="file"]');
// Create a new File object
const myFile = new File(['Hello World!'], 'myFile.txt', {
type: 'text/plain',
lastModified: new Date(),
});
// Now let's create a DataTransfer to get a FileList
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);
fileInput.files = dataTransfer.files;
</script>
You need to create a DataTransfer and set the .files property of the input.
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);//your file(s) reference(s)
document.getElementById('input_field').files = dataTransfer.files;
Define in html:
<input type="hidden" name="image" id="image"/>
In JS:
ajax.jsonRpc("/consulta/dni", 'call', {'document_number': document_number})
.then(function (data) {
if (data.error){
...;
}
else {
$('#image').val(data.image);
}
})
After:
<input type="hidden" name="image" id="image" value="/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8U..."/>
<button type="submit">Submit</button>
Actually we can do it.
we can set the file value default by using webbrowser control in c# using FormToMultipartPostData Library.We have to download and include this Library in our project. Webbrowser enables the user to navigate Web pages inside form.
Once the web page loaded , the script inside the webBrowser1_DocumentCompleted will be executed.
So,
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
FormToMultipartPostData postData =
new FormToMultipartPostData(webBrowser1, form);
postData.SetFile("fileField", #"C:\windows\win.ini");
postData.Submit();
}
Refer the below link for downloading and complete reference.
https://www.codeproject.com/Articles/28917/Setting-a-file-to-upload-inside-the-WebBrowser-com
I'm trying to generate a zip archive of icons on-the-fly and stream the response to the user to download, via a JSON POST request.
The zip itself is created and the response is returned, but the client-side is not prompted to download the file, and the response is garbled (which I assume is the contents of the archive).
app.post('/download', function(request, response) {
var icons = request.body;
var filename = 'icons.zip';
response.attachment(filename);
var zip = Archiver('zip');
zip.on('finish', function(error) {
return response.end();
});
zip.pipe(response);
for (var i = 0; i < icons.length; i++) {
var icon = getIcon(icons[i]);
zip.append(fs.createReadStream('public/' + icon.svg), { name: icon.title + '.svg' });
}
zip.finalize();
});
I'm wondering if there's anything missing from the server-side code that's preventing the download on the client-side, but from the example I've followed (https://github.com/archiverjs/node-archiver/blob/master/examples/express.js), it doesn't seem to be the case.
Here's some screenshots of the request made and the response received:
AJAX calls don't trigger file downloads in a browser, so you need to work around that.
One possibility is to change the request from a POST to a GET and put the names of the icons in the URL as parameters.
Your Express route would look like this:
app.get('/download/*?', function(request, response) {
// Make sure icons names were provided:
if (! request.params[0]) {
return response.sendStatus(400);
}
// Split on `/`, which is used as separator between icon names:
var icons = request.params[0].split(/\//);
// The rest can be the same
...
});
Client-side, you would use this:
location.href = 'http://your-server/download/Chevron%20Down/Close/Trash';
(obviously you can also generate that URL dynamically based on user input, as long as you make sure that the icon names are properly URL-encoded)