I know that posts with similar titles exist, but it doesn't work for me its how I try to achieve that:
WebApi
public async Task<HttpResponseMessage> ExportAnalyticsData([FromODataUri] int siteId, [FromODataUri] string start, [FromODataUri] string end) {
DateTime startDate = Date.Parse(start);
DateTime endDate = Date.Parse(end);
using (ZipFile zip = new ZipFile()) {
using (var DailyLogLanguagesCsv = new CsvWriter(new StreamWriter("src"))) {
var dailyLogLanguages = await _dbContext.AggregateDailyLogSiteObjectsByDates(siteId, startDate, endDate).ToListAsync();
DailyLogLanguagesCsv.WriteRecords(dailyLogLanguages);
zip.AddFile("src");
}
using (var DailyLogSiteObjectsCsv = new CsvWriter(new StreamWriter("src"))) {
var dailyLogSiteObjects = await _dbContext.AggregateDailyLogSiteObjectsByDates(siteId, startDate, endDate).ToListAsync();
DailyLogSiteObjectsCsv.WriteRecords(dailyLogSiteObjects);
zip.AddFile("src");
}
zip.Save("src");
HttpResponseMessage result = null;
var localFilePath = HttpContext.Current.Server.MapPath("src");
if (!File.Exists(localFilePath)) {
result = Request.CreateResponse(HttpStatusCode.Gone);
} else {
// Serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "Analytics";
}
return result;
}
}
AngularJs
$scope.exportData = function () {
apiService.dailyLog.exportAnalyticsData($scope.siteId, $scope.startDate, $scope.finishDate).then(function (response) {
debugger;
var blob = new Blob([response.data], { type: "application/zip" });
saveAs(blob, "analytics.zip");
})
};
function saveAs(blob, fileName) {
var url = window.URL.createObjectURL(blob);
var doc = document.createElement("a");
doc.href = url;
doc.download = fileName;
doc.click();
window.URL.revokeObjectURL(url);
}
And when I download a file I get information that the file is damaged. It only happens when I return zip file. It works well for csv.
After #wannadream suggestions and edited my code
else
{
// Serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "Analytics";
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
}
I have such problem when i try to open downloaded zip.
Try accessing the WebAPI controller action through a normal browser, and see if the ZIP it downloads can open. If it can't, then your problem is in your WebAPI.
zip.AddFile("src"); and then zip.Save("src"); ? It does not make sense.
You are zipping 'src' with target name 'src'. Try another name for zip file.
zip.Save("target")
var localFilePath = HttpContext.Current.Server.MapPath("target");
Try set this:
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
I resolve it by set a type responseType
{ type: "application/octet-stream", responseType: 'arraybuffer' }
and the same thing in my apiService
$http.get(serviceBase + path), {responseType:'arraybuffer'});
This can be done using DotNetZip and set the response type as arraybuffer, check below code for complete understanding.
1.WebApi Controller
[HttpPost]
[Route("GetContactFileLink")]
public HttpResponseMessage GetContactFileLink([FromBody]JObject obj)
{
string exportURL = "d:\\xxxx.text";//replace with your filepath
var fileName = obj["filename"].ToObject<string>();
exportURL = exportURL+fileName;
var resullt = CreateZipFile(exportURL);
return resullt;
}
private HttpResponseMessage CreateZipFile(string directoryPath)
{
try
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
using (ZipFile zip = new ZipFile())
{
zip.AlternateEncodingUsage = ZipOption.AsNecessary;
zip.AddFile(directoryPath, "");
//Set the Name of Zip File.
string zipName = String.Format("Zip_{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
using (MemoryStream memoryStream = new MemoryStream())
{
//Save the Zip File to MemoryStream.
zip.Save(memoryStream);
//Set the Response Content.
response.Content = new ByteArrayContent(memoryStream.ToArray());
//Set the Response Content Length.
response.Content.Headers.ContentLength = memoryStream.ToArray().LongLength;
//Set the Content Disposition Header Value and FileName.
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
//Set the File Content Type.
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
return response;
}
}
}
catch(Exception ex)
{
throw new ApplicationException("Invald file path or file not exsist");
}
}
2.Angular component
function getcontactFileLink(token, params) {
return $http.post('api/event/GetContactFileLink', params, { headers: { 'Authorization': 'Bearer ' + token, 'CultureCode': cc }, 'responseType': 'arraybuffer' }).then(response);
function response(response) {
return response;
}
}
function showcontactfile(item) {
usSpinnerService.spin('spinner-1');
var params = {};
params.filename = item.filename;
EventListingProcess.getcontactFileLink(accessToken, params).then(function (result) {
var blob = new Blob([result.data], { type: "application/zip" });
var fileName = item.filename+".zip";
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display:none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}).catch(function (error) {
vm.message = frameworkFactory.decodeURI(error.statusText);
//frameworkFactory.translate(vm, 'message', error.statusText);
}).finally(function () {
usSpinnerService.stop('spinner-1');
});
}
Related
I have a string called csv that is literally just that, things like "name,lastname,age,height,etc"
Then I send it to the backend like this..
var csv = exportRequests.GetCSV();
var filename = string.Format("{0}-{1}-{2:yyyy-MM-dd_hh-mm-ss-tt}.csv", "Request", requestStatus.ToUpperInvariant(), DateTime.Now);
var stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(csv);
writer.Flush();
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.GetBuffer())
};
result.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = filename
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("text/csv");
//var test = new FileDetailViewModel();
//test.Name = filename;
//test.Rows = csv;
return Ok(result);
I then read it on the backend, but where is the actual content?? Surely the bytes should be somewhere. The content property only has the headers.. This is taking place on an old system using $.ajax to make the call.
Thanks
I do not think it is possible to read content via HttpResponseMessage in JavaScript. You can only download content.
public HttpResponseMessage GetCsv()
{
var csv = exportRequests.GetCSV();
var filename = string.Format("{0}-{1}-{2:yyyy-MM-dd_hh-mm-ss-tt}.csv", "Request", requestStatus.ToUpperInvariant(), DateTime.Now);
var stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(csv);
writer.Flush();
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(stream.GetBuffer())
};
result.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = filename
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
return result;
}
download script
window.open('/api/controller/GetCsv', '_blank', '');
If you want to display csv content you can use the following code
[HttpPost]
public String GetCsv()
{
return exportRequests.GetCSV();
}
script
$('#btngetcsv').click(function() {
$.ajax({
url: "/api/controller/GetCsv",
data: {},
type: "Post",
dataType: "Json",
success: function(result) {
var arr = csvToArray(result);
for (var i = 0; i < arr.length; i++) {
var name = arr[i].name;
var lastname = arr[i].lastname;
//etc...........
}
},
error: function() {
}
});
});
function csvToArray(str, delimiter = ",") {
// slice from start of text to the first \n index
// use split to create an array from string by delimiter
const headers = str.slice(0, str.indexOf("\n")).split(delimiter);
// slice from \n index + 1 to the end of the text
// use split to create an array of each csv value row
const rows = str.slice(str.indexOf("\n") + 1).split("\n");
// Map the rows
// split values from each row into an array
// use headers.reduce to create an object
// object properties derived from headers:values
// the object passed as an element of the array
const arr = rows.map(function(row) {
const values = row.split(delimiter);
const el = headers.reduce(function(object, header, index) {
object[header] = values[index];
return object;
}, {});
return el;
});
// return the array
return arr;
}
must be a simple question but I've been struggling for a week with it. I have a super simple jquery based audio capture - what I just want is to save it as a file based on a controller action. The problem is that I can't figure out how to pass blob file to the controller. This is the code I have to capture audio (see below). With image I can just use
document.getElementById("canvas").toDataURL("image/png");
then pass it to controller and save it as image, something like this:
using (FileStream fs = new FileStream(fileNameWitPath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(imageData);
bw.Write(data);
bw.Close();
}
fs.Close();
}
so ideally I would want something akin to how I save images.
$(function () {
$('body').append(
$('<button/>')
.attr("id", "start")
.html("start")
).append(
$('<button/>')
.attr("id", "stop")
.html("stop")
).append(
$('<div/>').
attr("id", "ul")
)
let log = console.log.bind(console),
ul = $('#ul')[0],
start = $('#start')[0],
stop = $('#stop')[0],
stream,
recorder,
counter = 1,
chunks,
media;
media = {
tag: 'audio',
type: 'audio/ogg',
ext: '.ogg',
gUM: { audio: true }
}
navigator.mediaDevices.getUserMedia(media.gUM).then(_stream => {
stream = _stream;
recorder = new MediaRecorder(stream);
recorder.ondataavailable = e => {
chunks.push(e.data);
if (recorder.state == 'inactive') makeLink();
};
log('got media successfully');
}).catch(log);
start.onclick = e => {
start.disabled = true;
stop.removeAttribute('disabled');
chunks = [];
recorder.start();
}
stop.onclick = e => {
stop.disabled = true;
recorder.stop();
start.removeAttribute('disabled');
}
function makeLink() {
let blob = new Blob(chunks, { type: media.type })
, url = URL.createObjectURL(blob)
, div = document.createElement('div')
, mt = document.createElement(media.tag)
, hf = document.createElement('a')
;
mt.controls = true;
mt.src = url;
hf.href = url;
hf.download = `${counter++}${media.ext}`;
hf.innerHTML = `donwload ${hf.download}`;
div.appendChild(mt);
ul.appendChild(div);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Much appreciated
So just in case anyone else stumples on it, as expected it was quite simple (not the cleanest code but here you go):
create a new Blob value:
recorder.ondataavailable = e => {
chunks.push(e.data);
superBuffer = new Blob(chunks, { type: 'audio/ogg' });
if (recorder.state == 'inactive') makeLink(); //console.log(e.data)
Then use Ajax to send this to server:
var reader = new window.FileReader();
reader.readAsDataURL(superBuffer);
reader.onloadend = function () {
base64 = reader.result;
base64 = base64.split(',')[1];
$.ajax({
url: 'MyController/Action1',
type: 'POST',
data: {
audioname: "hello",//obviously change to something dynamic
chunks: base64
},
success: function (response) { console.log(response); },
error: function (response) { console.log(response); }
});
Then in the code-behind:
[HttpPost]
public IActionResult Action1(string audioname, string chunks)
{
string fileNameWitPath = Path.Combine(_hostingEnvironment.WebRootPath, "audio", "test.ogg");
using (FileStream fs = new FileStream(fileNameWitPath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(chunks);
bw.Write(data);
bw.Close();
}
fs.Close();
}
return Content(chunks) ;//this is for testing - sends back full chunk on success, would probably just want some confirm all is good message
}
Note this is work in progress obviously with things to fill, but in general works
I have an encoded base64 data from an API response and stored in a variable encodedBase64.
let encodedBase64 = 'some base64 encoded long data';
function base64ToArrayBuffer(base64) {
var binaryString = window.atob(base64);
console.log('binaryString ', binaryString);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
}
function saveByteArray(reportName, byte) {
var blob = new Blob([byte], {type: "application/pdf"});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
var fileName = reportName;
link.download = fileName;
link.click();
};
var sampleArr = base64ToArrayBuffer(encodedBase64);
saveByteArray("Sample Report", sampleArr);
after executing this code i am able to download pdf file names SampleReport.pdf but when i open this it is showing Failed to load PDF document. error
what is the wrong in my code ?
difficult to get it done using front end side
but it can be done easily using Nodejs using the following code.
fs.writeFile('pdfFileName.pdf', base64DataString, {encoding: 'base64'}, error => {
if (error) {
throw error;
} else {
console.log('buffer saved!');
}
});
This question already has an answer here:
How to POST binary files with AngularJS (with upload DEMO)
(1 answer)
Closed 4 years ago.
I have a file upload module.its working well with postman with no content type.but in code always file count is getting as 0 in backend api.if anyone knows what i am doing wrong,please help me. thanks
here is my back end api`
public async Task<HttpResponseMessage> PostUserImage()
{
Dictionary<string, object> dict = new Dictionary<string, object>();
try
{
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
var postedFile = httpRequest.Files[file];
if (postedFile != null && postedFile.ContentLength > 0)
{
int MaxContentLength = 1024 * 1024 * 1; //Size = 1 MB
IList<string> AllowedFileExtensions = new List<string> { ".jpg", ".gif", ".png" };
var ext = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf('.'));
var extension = ext.ToLower();
if (!AllowedFileExtensions.Contains(extension))
{
var message = string.Format("Please Upload image of type .jpg,.gif,.png.");
dict.Add("error", message);
return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
}
else if (postedFile.ContentLength > MaxContentLength)
{
var message = string.Format("Please Upload a file upto 1 mb.");
dict.Add("error", message);
return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
}
else
{
var filePath = HttpContext.Current.Server.MapPath("~/Image/" + postedFile.FileName + extension);
postedFile.SaveAs(filePath);
}
}
var message1 = string.Format("Image Updated Successfully.");
return Request.CreateErrorResponse(HttpStatusCode.Created, message1); ;
}
var res = string.Format("Please Upload a image.");
dict.Add("error", res);
return Request.CreateResponse(HttpStatusCode.NotFound, dict);
}
catch (Exception ex)
{
var res = string.Format("some Message");
dict.Add("error", res);
return Request.CreateResponse(HttpStatusCode.NotFound, dict);
}
}`
this is what i am getting after posting through postman
and this is what i am getting in my developer console.
my angular service foe uploading`
uploadimage:function(file,operation){
var deferred = $q.defer();
var httpReq = {
method: operation,
url: '/API/Customers/PostUserImage',
data:file,
transformRequest: angular.identity,
headers: {
'content-type': 'multipart/form-data'
},
onSuccess: function (response, status) {
deferred.resolve(response);
},
onError: function (response) {
deferred.reject(response);
}
};
httpService.call(httpReq);
return deferred.promise;
}`
this the controller code for appending to form data`
function readURL(input) {
debugger;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#imagePreview').css('background-image', 'url('+e.target.result +')');
$('#imagePreview').hide();
$('#imagePreview').fadeIn(650);
}
reader.readAsDataURL(input.files[0]);
var filesformdata = new FormData();
angular.forEach(input.files, function (value, key) {
filesformdata.append(key, value);
});
for (var pair of filesformdata.entries()) {
console.log(pair[0] + ', ' + pair[1]);
console.log(pair[1]);
}
profileService.uploadimage(filesformdata,"POST").then(function(response){
toastr.success("profilepicture changed");
});
}
}
and here is http request `
use API like
public async Task<HttpResponseMessage> MethodName()
{
if (HttpContext.Current.Request.ContentType == "application/x-www-form-urlencoded")
{
var ParameterName = int.Parse(HttpContext.Current.Request.Form.GetValues("ParameterName")[0].ToString());
}
else
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
}
var response = Request.CreateResponse(objreturn);
return response;
}
When sending non-alphanumeric file or big payload, you should be using form enctype attribute value of "multipart/form-data".
<form enctype="multipart/form-data" ...
Example: HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME
public async Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
I'm wondering how to upload file onto Firebase's storage via URL instead of input (for example). I'm scrapping images from a website and retrieving their URLS. I want to pass those URLS through a foreach statement and upload them to Firebase's storage. Right now, I have the firebase upload-via-input working with this code:
var auth = firebase.auth();
var storageRef = firebase.storage().ref();
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var file = evt.target.files[0];
var metadata = {
'contentType': file.type
};
// Push to child path.
var uploadTask = storageRef.child('images/' + file.name).put(file, metadata);
// Listen for errors and completion of the upload.
// [START oncomplete]
uploadTask.on('state_changed', null, function(error) {
// [START onfailure]
console.error('Upload failed:', error);
// [END onfailure]
}, function() {
console.log('Uploaded',uploadTask.snapshot.totalBytes,'bytes.');
console.log(uploadTask.snapshot.metadata);
var url = uploadTask.snapshot.metadata.downloadURLs[0];
console.log('File available at', url);
// [START_EXCLUDE]
document.getElementById('linkbox').innerHTML = 'Click For File';}
Question what do I replace
var file = evt.target.files[0];
with to make it work with external URL instead of a manual upload process?
var file = "http://i.imgur.com/eECefMJ.jpg"; doesn't work!
There's no need to use Firebase Storage if all you're doing is saving a url path. Firebase Storage is for physical files, while the Firebase Realtime Database could be used for structured data.
Example . once you get the image url from the external site this is all you will need :
var externalImageUrl = 'https://foo.com/images/image.png';
then you would store this in your json structured database:
databaseReference.child('whatever').set(externalImageUrl);
OR
If you want to actually download the physical images straight from external site to storage then this will require making an http request and receiving a blob response or probably may require a server side language ..
Javascript Solution : How to save a file from a url with javascript
PHP Solution : Saving image from PHP URL
This answer is similar to #HalesEnchanted's answer but with less code. In this case it's done with a Cloud Function but I assume the same can be done from the front end. Notice too how createWriteStream() has an options parameter similar to bucket.upload().
const fetch = require("node-fetch");
const bucket = admin.storage().bucket('my-bucket');
const file = bucket.file('path/to/image.jpg');
fetch('https://example.com/image.jpg').then((res: any) => {
const contentType = res.headers.get('content-type');
const writeStream = file.createWriteStream({
metadata: {
contentType,
metadata: {
myValue: 123
}
}
});
res.body.pipe(writeStream);
});
Javascript solution to this using fetch command.
var remoteimageurl = "https://example.com/images/photo.jpg"
var filename = "images/photo.jpg"
fetch(remoteimageurl).then(res => {
return res.blob();
}).then(blob => {
//uploading blob to firebase storage
firebase.storage().ref().child(filename).put(blob).then(function(snapshot) {
return snapshot.ref.getDownloadURL()
}).then(url => {
console.log("Firebase storage image uploaded : ", url);
})
}).catch(error => {
console.error(error);
});
Hopefully this helps somebody else :)
// Download a file form a url.
function saveFile(url) {
// Get file name from url.
var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", transferComplete);
xhr.addEventListener("error", transferFailed);
xhr.addEventListener("abort", transferCanceled);
xhr.responseType = 'blob';
xhr.onload = function() {
var a = document.createElement('a');
a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
a.download = filename; // Set the file name.
a.style.display = 'none';
document.body.appendChild(a);
a.click();
delete a;
if (this.status === 200) {
// `blob` response
console.log(this.response);
var reader = new FileReader();
reader.onload = function(e) {
var auth = firebase.auth();
var storageRef = firebase.storage().ref();
var metadata = {
'contentType': 'image/jpeg'
};
var file = e.target.result;
var base64result = reader.result.split(',')[1];
var blob = b64toBlob(base64result);
console.log(blob);
var uploadTask = storageRef.child('images/' + filename).put(blob, metadata);
uploadTask.on('state_changed', null, function(error) {
// [START onfailure]
console.error('Upload failed:', error);
// [END onfailure]
}, function() {
console.log('Uploaded',uploadTask.snapshot.totalBytes,'bytes.');
console.log(uploadTask.snapshot.metadata);
var download = uploadTask.snapshot.metadata.downloadURLs[0];
console.log('File available at', download);
// [START_EXCLUDE]
document.getElementById('linkbox').innerHTML = 'Click For File';
// [END_EXCLUDE]
});
// `data-uri`
};
reader.readAsDataURL(this.response);
};
};
xhr.open('GET', url);
xhr.send();
}
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
function transferComplete(evt) {
window.onload = function() {
// Sign the user in anonymously since accessing Storage requires the user to be authorized.
auth.signInAnonymously().then(function(user) {
console.log('Anonymous Sign In Success', user);
document.getElementById('file').disabled = false;
}).catch(function(error) {
console.error('Anonymous Sign In Error', error);
});
}
}
function transferFailed(evt) {
console.log("An error occurred while transferring the file.");
}
function transferCanceled(evt) {
console.log("The transfer has been canceled by the user.");
}