Error loading(insert) images in CKeditor? - javascript

When I write my functions as below, you can see that there is a record as seen in the image. Where exactly is the problem?
Which is the function that records like in the image?
The image saves as I want, but it saves to the database as in the image.
I did according to the answer in How to use custom upload adapter on ASP.Net Core - CKEDITOR 5? but I can't solve the problem
!!How can I give this.url to src?
class MyUploadAdapter
{
constructor(loader) {
// The file loader instance to use during the upload.
this.loader = loader;
this.urls = '/tr/UnitType/DocUploadImage';
}
// Starts the upload process.
upload() {
return this.loader.file.then(file => new Promise((resolve, reject) => {
this._initRequest();
this._initListeners(resolve, reject, file);
this._sendRequest(file);
}));
}
// Aborts the upload process.
abort() {
if (this.xhr) {
this.xhr.abort();
}
}
_initRequest() {
const xhr = this.xhr = new XMLHttpRequest();
xhr.open('POST', this.urls, true);
xhr.responseType = 'json';
}
// Initializes XMLHttpRequest listeners.
_initListeners(resolve, reject, file) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = `Couldn't upload file: ${file.name}.`;
xhr.addEventListener('error', () => reject(genericErrorText));
xhr.addEventListener('abort', () => reject());
xhr.addEventListener('load', () => {
const response = xhr.response;
if (!response || response.error) {
return reject(response && response.error ? response.error.message : genericErrorText);
}
resolve({
default: response.urls
});
});
if (xhr.upload) {
xhr.upload.addEventListener('progress', evt => {
if (evt.lengthComputable) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
});
}
}
// Prepares the data and sends the request.
_sendRequest(file) {
// Prepare the form data.
const data = new FormData();
data.append('upload', file);
this.xhr.send(data);
}
}
function MyCustomUploadAdapterPlugin(editor) {
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return new MyUploadAdapter(loader);
};
}
public async Task<JsonResult> DocUploadImage()
{
try
{
var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
var webRootPath = config["AppSettings:urunResimPath"].ToString();
var uploads = Path.Combine(webRootPath, "assets");
var filePath = Path.Combine(uploads, "rich-text");
var urls = new List<string>();
//If folder of new key is not exist, create the folder.
if (!Directory.Exists(filePath)) Directory.CreateDirectory(filePath);
foreach (var contentFile in Request.Form.Files)
{
if (contentFile != null && contentFile.Length > 0)
{
await contentFile.CopyToAsync(new FileStream($"{filePath}\\{contentFile.FileName}", FileMode.Create));
urls.Add($"{HttpContext.Request.Host}/rich-text/{contentFile.FileName}");
}
}
return Json(urls);
}
catch (Exception e)
{
return Json(new { error = new { message = e.Message } });
}
}

Related

Preventing duplicate files in an input file

I'm using loodash cloneDeep to upload files, however I need files to not be duplicated and only be able to upload a file once. How can I do this using cloneDeep?
I don't know how to do it, I googled, but the solution was only for jquery
const [files, setFiles] = useState([]);
const onSelectFile = (e) => {
try {
let fileArr = cloneDeep(files);
let promises = [];
for (let file of e.target.files) {
promises.push(
new Promise((resolve, reject) => {
const fileName = file.name
const type = file.type;
let reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (evt) {
const fileData = evt.target.result;
fileArr.push({
name: fileName,
type: type,
data: fileData,
comment: "",
id: `${new Date().getTime()}_${fileName}`,
canDelete: true
});
if (typeof props.onFileSelected == "function")
props.onFileSelected(fileArr);
resolve(true);
}
reader.onerror = function (evt) {
console.log("error reading file");
reject(false);
}
})
);
}
Promise.all(promises).then(r => {
setFiles(fileArr);
})
}
catch(e) {
console.log(e);
}
}
If relying on the filenames is enough, you can try to store them to check if it has been uploaded already :
const [files, setFiles] = useState([]);
//state to store uploaded file's name
const [fileNames, setFileNames] = useState([]);
const onSelectFile = (e) => {
try {
let fileArr = cloneDeep(files);
let promises = [];
for (let file of e.target.files) {
promises.push(
new Promise((resolve, reject) => {
const fileName = file.name
//if the file has not been already uploaded
if (!fileNames.includes(fileName)) {
//add the current fileName in state
setFileNames([fileName, ...fileNames]);
const type = file.type;
let reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (evt) {
const fileData = evt.target.result;
fileArr.push({
name: fileName,
type: type,
data: fileData,
comment: "",
id: `${new Date().getTime()}_${fileName}`,
canDelete: true
});
if (typeof props.onFileSelected == "function")
props.onFileSelected(fileArr);
resolve(true);
}
reader.onerror = function (evt) {
console.log("error reading file");
reject(false);
}
} else {
alert("File has already been uploaded");
reject(false);
}
})
);
}
Promise.all(promises).then(r => {
setFiles(fileArr);
})
}
catch(e) {
console.log(e);
}
}
Note: this will not prevent the case when the user upload a file, then refresh the website and upload the same file again
If you want to prevent that you have to ask your backend if the file has already been upload or not.

Submit form in Ajax without JQuery

I'm trying to follow this guide to update a form field when the user change another field.
I've correctly setup my FormTypes, but I'm having trouble submitting the form in Ajax without JQuery.
I have 2 select :
const blockchain = document.getElementById('strategy_farming_blockchain');
const dapp = document.getElementById('strategy_farming_dapp');
const csrf = document.getElementById('strategy_farming__token');
The blockchain field is supposed to update the dapp field.
If I submit the whole form, it's working :
blockchain.addEventListener('change', function () {
const form = this.closest('form');
const method = form.method;
const url = form.action;
var request = new XMLHttpRequest();
request.open(method, url, true);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.onload = function () {
if (this.status >= 200 && this.status < 400) {
//Success
const html = new DOMParser().parseFromString(this.response, 'text/html');
dapp.innerHTML = html.querySelector('#strategy_farming_dapp').innerHTML;
} else {
//Error from server
console.log('Server error');
}
};
request.onerror = function () {
//Connection error
console.log('Connection error');
};
request.send(new FormData(form));
});
But I'm not supposed to submit the whole form, I'm supposed to submit only the blockchain value
I tried a lot of things, like
var formdata = new FormData(form);
formdata.delete(dapp.name);
request.send(formdata);
// It's working for a new entity, but if I'm editing one, it's not updating the dapp field...
or
var formdata = new FormData();
formdata.append(this.name, this.value);
formdata.append(csrf.name, csrf.value);
request.send(formdata);
// It's working in a NEW action, but not in an EDIT action...
or
var data = {};
data[this.name] = this.value;
request.send(data);
//or
request.send(JSON.stringify(data));
//If I dump($request->request) in the controller, it seems like there's no data...
//Or the request isn't parsed correctly, or there's something missing ?
I also tried with encodeURIComponent...
I'm out of ideas... Any ideas ? Thanks !
So I chose to use FormData and remove the dapp field.
const blockchain = document.getElementById('strategy_farming_blockchain');
const dapp = document.getElementById('strategy_farming_dapp');
blockchain.addEventListener('change', function () {
const form = this.closest('form');
const method = form.method;
const url = form.action;
var request = new XMLHttpRequest();
request.withCredentials = true;
request.open(method, url, true);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.onload = function () {
if (this.status >= 200 && this.status < 400) {
//Success
const html = new DOMParser().parseFromString(this.response, 'text/html');
dapp.innerHTML = html.querySelector('#strategy_farming_dapp').innerHTML;
} else {
//Error from server
console.log('Server error');
}
};
request.onerror = function () {
//Connection error
console.log('Connection error');
};
var formdata = new FormData(form);
formdata.set(dapp.name, "");
request.send(formdata);
});
Here's the FormType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
//...
->add('blockchain', EntityType::class, [
'required' => false,
'class' => Blockchain::class,
'attr' => ['class' => 'js-select2'],
]);
$formModifier = function (FormInterface $form, Blockchain $blockchain = null) {
$dapps = null === $blockchain ? [] : $blockchain->getDapps();
$form->add('dapp', EntityType::class, [
'class' => Dapp::class,
'required' => true,
'choices' => $dapps,
'placeholder' => 'My placeholder',
'attr' => ['class' => 'js-select2'],
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
/**
* #var StrategyFarming $data
*/
$data = $event->getData();
$blockchain = $data->getDapp() ? $data->getDapp()->getBlockchain() : null;
$formModifier($event->getForm(), $blockchain);
}
);
$builder->get('blockchain')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$blockchain = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $blockchain);
}
);
}
In order for this to work, I had to add the blockchain field to my Form's Entity, so that the Request handle the field :
/**
* Not persisted
* #var Blockchain
*/
private $blockchain;
public function getBlockchain(): ?Blockchain
{
if ($this->blockchain === null && $this->dapp !== null && $this->dapp->getBlockchain() !== $this->blockchain) {
$this->blockchain = $this->dapp->getBlockchain();
}
return $this->blockchain;
}
public function setBlockchain(?Blockchain $blockchain): self
{
$this->blockchain = $blockchain;
return $this;
}

Event { "isTrusted": false } using Expo and XMLHttpRequest

I'm trying to upload(send) a PDF to server using below code snippet:
const xhr = new XMLHttpRequest();
xhr.open("POST", "/upload");
xhr.onload = (e) => {
const response = JSON.parse(xhr.response);
console.log(response);
};
xhr.onerror = (error) => {
console.log(error);
};
xhr.ontimeout = (e) => {
console.log(e, "upload timeout");
};
const formData = new FormData();
formData.append("fileToUpload", {
uri: fileToUpload.uri,
type: `*/*`,
name: fileToUpload.name,
});
xhr.send(formData);
if (xhr.upload) {
xhr.upload.onprogress = ({ total, loaded }) => {
const uploadProgress = loaded / total;
console.log(uploadProgress);
};
}
In response, I'm receiving following error:
Event {
"isTrusted": false,
}
Any other approach to upload a file (pdf) to server using Expo, would also be appreciated.
Thanks
I figured out, that the actual problem was- In android while selecting a file on Android device, DocumentPicker in Expo doesn't provide the complete path to the file, you have to manage it on your own, As I did below.
import * as DocumentPicker from "expo-document-picker";
...
const [singleFile, setSingleFile] = useState(null);
const onSubmit = async () => {
try {
// upload the file
const formData = new FormData();
formData.append("fileToUpload", singleFile);
axios.defaults.headers.post["Content-Type"] =
"multipart/form-data";
const uploadResp = await axios.post(
"/upload",
formData
);
if (uploadResp.status === 200) {
// file uploaded successfully
}
} catch (error) {
}
};
const selectFile = async () => {
await DocumentPicker.getDocumentAsync({
type: "application/pdf",
copyToCacheDirectory: true,
})
.then((response) => {
if (response.type == "success") {
let { name, size, uri } = response;
// >>>>>>>>>>>>> the bug's solution <<<<<<<<<<<<<<<
if (Platform.OS === "android" && uri[0] === "/") {
uri = `file://${uri}`;
uri = uri.replace(/%/g, "%25");
}
let nameParts = name.split(".");
let fileType = nameParts[nameParts.length - 1];
setSingleFile({
name: name,
size: size,
uri: uri,
type: "application/" + fileType,
});
} else {
setSingleFile(null);
}
})
.catch((err) => {
console.error(err);
});
};
...
<TouchableOpacity activeOpacity={0.6} onPress={() => selectFile()}>
<View >
<Text >
Select File
</Text>
</View>
</TouchableOpacity>
...

How should customRequest be set in the Ant Design Upload component to work with an XMLHttpRequest?

I have a complete mess of a component. Right now I pass a function I have been trying a million things I can not make it work.
export default class DatafileUpload extends Component {
initialState = {
fileUploading: false,
fileList: [],
status: 'empty', // 'empty' | 'active' | 'success' | 'exception'
file: {}
}
state = this.initialState
static propTypes = {
userId: PropTypes.string.isRequired,
datasetId: PropTypes.string.isRequired
}
scrubFilename = (filename) => filename.replace(/[^\w\d_\-.]+/ig, '')
requestSignedS3Url = (file) => {
const filename = this.scrubFilename(file.name)
const params = {
userId: this.props.userId,
contentType: file.type,
Key: `${filename}`
};
return api.get('/s3/signUpload', { params })
.then(response => {
return response.data;
})
.catch(error => {
console.error(error);
});
}
uploadFile = (file) => {
this.requestSignedS3Url(file)
.then(signResult => this.uploadToS3(file, signResult))
.catch(error => console.log(error))
}
createCORSRequest = (method, url, opts) => {
opts = opts || {};
let xhr = new XMLHttpRequest();
if (xhr.withCredentials != null) {
xhr.open(method, url, true);
if (opts.withCredentials != null) {
xhr.withCredentials = opts.withCredentials;
}
} else if (typeof XDomainRequest !== "undefined") {
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
};
stepFunctions = () => {
return {
preprocess: (file) => {
console.log('Pre-process: ' + file.name);
},
onProgress: (percent, message, file) => {
this.setState({ fileUploading: true })
console.log('Upload progress: ' + percent + '% ' + message);
},
onFinish: (signResult) => {
this.setState({ fileUploading: false })
console.log("Upload finished: " + signResult.publicUrl)
},
onError: (message) => {
this.setState({ fileUploading: false })
console.log("Upload error: " + message);
},
scrubFilename: (filename) => {
return filename.replace(/[^\w\d_\-\.]+/ig, '');
},
onFinishS3Put: (signResult, file) => {
console.log(signResult)
return console.log('base.onFinishS3Put()', signResult.publicUrl);
}
}
}
uploadToS3 = async (file, signResult) => {
const xhr = await this.createCORSRequest('PUT', signResult.signedUrl);
const functions = this.stepFunctions()
functions.preprocess(file)
if (!xhr) {
functions.onError('CORS not supported', file);
} else {
xhr.onload = () => {
if (xhr.status === 200) {
functions.onProgress(100, 'Upload completed', file);
return functions.onFinishS3Put('potatopotato', file);
} else {
return functions.onError('Upload error: ' + xhr.status, file);
}
};
xhr.onerror = () => {
return functions.onError('XHR error', file);
};
xhr.upload.onprogress = (e) => {
let percentLoaded;
if (e.lengthComputable) {
percentLoaded = Math.round((e.loaded / e.total) * 100);
return functions.onProgress(percentLoaded, percentLoaded === 100 ? 'Finalizing' : 'Uploading', file);
}
};
}
xhr.setRequestHeader('Content-Type', file.type);
if (signResult.headers) {
const signResultHeaders = signResult.headers
Object.keys(signResultHeaders).forEach(key => {
const val = signResultHeaders[key];
xhr.setRequestHeader(key, val);
})
}
xhr.setRequestHeader('x-amz-acl', 'public-read');
this.httprequest = xhr;
return xhr.send(file);
};
handleChange = ({ file, fileList }) => {
const functions = this.stepFunctions()
functions.preprocess(file)
if (!file) {
functions.onError('CORS not supported', file);
} else {
file.onload = () => {
if (file.status === 200) {
functions.onProgress(100, 'Upload completed', file);
return functions.onFinishS3Put('potatopotato', file);
} else {
return functions.onError('Upload error: ' + file.status, file);
}
};
file.onerror = () => {
return functions.onError('XHR error', file);
};
file.upload.onprogress = (e) => {
let percentLoaded;
if (e.lengthComputable) {
percentLoaded = Math.round((e.loaded / e.total) * 100);
return functions.onProgress(percentLoaded, percentLoaded === 100 ? 'Finalizing' : 'Uploading', file);
}
};
}
console.log('File: ', file)
// always setState
this.setState({ fileList });
}
render() {
const props = {
onChange: this.handleChange,
multiple: true,
name: "uploadFile",
defaultFileList: this.initialState.fileList,
data: this.uploadFile,
listType: "text",
customRequest: ????,
showUploadList: {
showPreviewIcon: true,
showRemoveIcon: true
},
onProgress: ( {percent} ) => {
this.setState({ fileUploading: true })
console.log('Upload progress: ' + percent + '% ' );
},
onError: (error, body) => {
this.setState({ fileUploading: false })
console.log("Upload error: " + error);
},
onSuccess: (body)=> {
console.log(body)
return console.log('base.onFinishS3Put()');
}
};
return (
<Upload {...props} fileList={this.state.fileList}>
<Button>
<Icon type="upload" /> Upload
</Button>
</Upload>
)
}
}
I know this code is a mess that doesn't make sense and have duplicated data all around. I want it to make it work and then clean up/optimse. Basically I am not able to make the component progress bar update nor with the onChange nor when I am trying to use the customRequest. When is customRequest called? This is not very abundant in explanations... I don't understand how does it do the replacement of Ajax upload.
I was struggling with that as well and then I found your question.
So the way I found to use customRequest and onChange is:
<Upload name="file" customRequest={this.customRequest} onChange={this.onChange}>
<Button>
<Icon type="upload" /> Click to Upload
</Button>
</Upload>
...
onChange = (info) => {
const reader = new FileReader();
reader.onloadend = (obj) => {
this.imageDataAsURL = obj.srcElement.result;
};
reader.readAsDataURL(info.file.originFileObj);
...
};
...
customRequest = ({ onSuccess, onError, file }) => {
const checkInfo = () => {
setTimeout(() => {
if (!this.imageDataAsURL) {
checkInfo();
} else {
this.uploadFile(file)
.then(() => {
onSuccess(null, file);
})
.catch(() => {
// call onError();
});
}
}, 100);
};
checkInfo();
};
There are probably better ways to do it, but I hope that helps you.
I struggled it a lot and find an efficient way to handle this case.
first- you should mess with the customRequest only when you need to change to body and the request type (like using post instead of 'put' or using xml or add another extra header).
for the signing Url you can send in the action prop callback which return a promise with the right Url to upload like:
handleUplaod = (file: any) => {
return new Promise(async (resolve, reject) => {
const fileName = `nameThatIwant.type`;
const url = await S3Fetcher.getPresignedUrl(fileName);
resolve(url);
});
and render like:
render(){
return(
....
<Upload
action={this.handleUplaod}
....
Upload>
the uploader take the url from the action prop.
the onChange method which is provided also will be called any time the status of upload is changed-
onChange# The function will be called when uploading is in progress,
completed or failed.
When uploading state change, it returns:
{ file: { /* ... / }, fileList: [ / ... / ], event: { / ...
*/ }, }
when upload started
you will need to activate the file reader from that.
like:
....
fileReader = new FileReader();
.....
onChange = (info) => {
if (!this.fileReader.onloadend) {
this.fileReader.onloadend = (obj) => {
this.setState({
image: obj.srcElement.result, //will be used for knowing load is finished.
});
};
// can be any other read function ( any reading function from
// previously created instance can be used )
this.fileReader.readAsArrayBuffer(info.file.originFileObj);
}
};
notice when completed stage that event=undefind
To update the UI from the upload events you should use the options variables from customRequest and call them whenever you need.
onSuccess- should be called when you finish uploading and it will change the loading icon to the file name.
onError- will paint the file name filed to red.
onProgress- will update the progress bar and should be called with {percent: [NUMBER]} for updating.
for example in my code-
customRequest = async option => {
const { onSuccess, onError, file, action, onProgress } = option;
const url = action;
await new Promise(resolve => this.waitUntilImageLoaded(resolve)); //in the next section
const { image } = this.state; // from onChange function above
const type = 'image/png';
axios
.put(url, Image, {
onUploadProgress: e => {
onProgress({ percent: (e.loaded / e.total) * 100 });
},
headers: {
'Content-Type': type,
},
})
.then(respones => {
/*......*/
onSuccess(respones.body);
})
.catch(err => {
/*......*/
onError(err);
});
};
waitUntilImageLoaded = resolve => {
setTimeout(() => {
this.state.image
? resolve() // from onChange method
: this.waitUntilImageLoaded(resolve);
}, 10);
};
I used axios but you can use other libraries as well
and the most important part-
render(){
return(
....
<Upload
onChange={this.onChange}
customRequest={this.customRequest}
...>

Angular 2 Synchronous File Upload

I am trying to upload a file to web api which takes the file as byte array using angular 2 application.
I am not able to pass the byte array from angular 2 page to web api. It looks like the File Reader read method is asynchronous. How do I make this as synchronous call or wait for the file content to be loaded before executing the next line of code?
Below is my code
//attachment on browse - when the browse button is clicked
//It only assign the file to a local variable (attachment)
fileChange = (event) => {
var files = event.target.files;
if (files.length > 0) {
this.attachment = files[0];
}
}
//when the submit button is clicked
onSubmit = () => {
//Read the content of the file and store it in local variable (fileData)
let fr = new FileReader();
let data = new Blob([this.attachment]);
fr.readAsArrayBuffer(data);
fr.onloadend = () => {
this.fileData = fr.result; //Note : This always "undefined"
};
//build the attachment object which will be sent to Web API
let attachment: Attachment = {
AttachmentId: '0',
FileName: this.form.controls["attachmentName"].value,
FileData: this.fileData
}
//build the purchase order object
let order: UpdatePurchaseOrder = {
SendEmail: true,
PurchaseOrderNumber: this.form.controls["purchaseOrderNumber"].value,
Attachment: attachment
}
//call the web api and pass the purchaseorder object
this.updatePoService
.updatePurchaseOrder(this.form.controls["purchaseOrderRequestId"].value, order)
.subscribe(data => {
if (data) {
this.saveSuccess = true;
}
else {
this.saveSuccess = false;
}
},
error => this.errors = error,
() => this.res = 'Completed'
);
}
Any hint would be useful.
regards,
-Alan-
You cannot make this async call synchronous. But you can take advantage of the observables to wait for the files to be read:
//when the submit button is clicked
onSubmit = () => {
let file = Observable.create((observer) => {
let fr = new FileReader();
let data = new Blob([this.attachment]);
fr.readAsArrayBuffer(data);
fr.onloadend = () => {
observer.next(fr.result);
observer.complete()
};
fr.onerror = (err) => {
observer.error(err)
}
fr.onabort = () => {
observer.error("aborted")
}
});
file.map((fileData) => {
//build the attachment object which will be sent to Web API
let attachment: Attachment = {
AttachmentId: '0',
FileName: this.form.controls["attachmentName"].value,
FileData: fileData
}
//build the purchase order object
let order: UpdatePurchaseOrder = {
SendEmail: true,
PurchaseOrderNumber: this.form.controls["purchaseOrderNumber"].value,
Attachment: attachment
}
return order;
})
.switchMap(order => this.updatePoService.updatePurchaseOrder(this.form.controls["purchaseOrderRequestId"].value, order))
.subscribe(data => {
if (data) {
this.saveSuccess = true;
} else {
this.saveSuccess = false;
}
},
error => this.errors = error,
() => this.res = 'Completed'
);
}
I arrived here looking for a solution for a similar issue. I'm performing requests to an endpoint which can response a binary blob if anything goes well or a JSON file in event of error.
this.httpClient.post(urlService, bodyRequest,
{responseType: 'blob', headers: headers})
.pipe(map((response: Response) => response),
catchError((err: Error | HttpErrorResponse) => {
if (err instanceof HttpErrorResponse) {
// here, err.error is a BLOB containing a JSON String with the error message
} else {
return throwError(ErrorDataService.overLoadError(err, message));
}
}));
As FileReaderSync apparently doesn't work in Angular6 I took n00dl3's solution (above) to throw the error after parsing the Blob content:
return this.httpClient.post(urlService, bodyRequest,
{responseType: 'blob', headers: headers})
.pipe(map((response: Response) => response),
catchError((err: Error | HttpErrorResponse) => {
const message = `In TtsService.getTts(${locale},${outputFormat}). ${err.message}`;
if (err instanceof HttpErrorResponse) {
const $errBlobReader: Observable<HttpErrorResponse> = Observable.create((observer) => {
const fr = new FileReader();
const errorBlob = err.error;
fr.readAsText(errorBlob, 'utf8');
fr.onloadend = () => {
const errMsg = JSON.parse(fr.result).message;
const msg = `In TtsService.getTts(${locale},${outputFormat}). ${errMsg}`;
observer.error(ErrorDataService.overLoadError(err, msg));
};
fr.onerror = (blobReadError) => {
observer.error(blobReadError);
};
fr.onabort = () => {
observer.error('aborted');
};
});
return $errBlobReader;
} else {
return throwError(ErrorDataService.overLoadError(err, message));
}
}));
Thanks! You really saved my day!

Categories

Resources