I'm trying to upload a file of whatever file extension. I'm uploading with a post, but when a run the function, it crash with an error:
"Cannot ready property 'length' of undefined "
upload(fileToUpload: File): Promise<FileResponse[]> {
const formData: FormData = new FormData();
formData.append('fileKey', fileToUpload, fileToUpload.name);
return this.http
.post<FileResponse[]>(this.baseUrl + this.urlUpload, formData, { headers: {'Content-Type': undefined }})
.toPromise().then((response) => {
console.log(response);
return response;
}).catch((e) => {
console.log(e);
return e;
});
}
This is my back end c#:
[HttpPost]
[Route("upload")]
[DisableFormValueModelBinding]
[RequestSizeLimit(104857600)]
public async Task<IActionResult> Upload()
{
var fileUploaded = await _fileService.UploadFile(FormOptions, reader);
return Json(new StandardResult<List<FileResponse>>(HttpStatusCode.Created, fileUploaded).Reply);
}
any solution to this?
I think that it's for this line:
{'Content-Type': undefined }
Or delete this line or put a generic "type", for example application/octet-stream
More information: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
Related
I am successfully using fetch to download an image file and store in a custom cache:
await fetch(url).then( async (response) => {
if (!response.ok) {
throw new TypeError("Bad response status");
}
return cache.put(url, response);
});
I would like to switch this to axios so I can display download progress and stop the download if needed. I am able to successfully download the file:
await axios({
method: 'get',
url: url,
responseType: 'blob'
}).then( async (response) => {
if (!response.ok) {
throw new TypeError("Bad response status");
}
return cache.put(url, response);
});
But it returns and error: Failed to execute 'put' on 'Cache': parameter 2 is not of type 'Response'.
Referencing this question I also tried to manually create the response:
var init = { status: 200 , statusText: 'OK', type: 'cors', url };
var myResponse = new Response(response, init);
return cache.put(url, myResponse);
But it seems to override the other information and doesn't store the blob data at all:
Is axios able to create the type of response that is needed for the Cache API?
Edited to add: I've also tried changing the responseType to stream which is what fetch seems to return, but that didn't work either.
We have an API (Spring Boot) for file uploads. If file exists it returns 409.
But js client doesn't read this response and fails with error "net::ERR_CONNECTION_ABORTED".
From wireshark dump I see that the backend sends the response and then closes the connection:
I think the problem is that js client doesn't read the response as soon as it available.
However, Postman is able to read the response correctly.
Is it possible to implement Postman's behavior in javascript?
I've tried to read response stream with Fetch API, but no luck.
Sample client code:
function uploadFile() {
try {
console.log("Start file upload");
const selectedFiles = document.getElementById('input').files;
if (selectedFiles.length == 0) {
alert("No file selected");
return;
}
const file = selectedFiles[0];
return fetch("http://localhost:9091/api/v1/storage/upload?fileId=/upload-test/test.mp4", {
method: 'PUT',
body: file,
headers: {
'Content-Type': 'application/octet-stream'
},
})
.then(response => {
console.log("Processing response");
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
return pump();
function pump() {
return reader.read().then(({ value, done }) => {
if (done) {
console.log("Finished stream reading");
return;
}
console.log(value);
return pump();
});
}
})
.catch((err) => console.error("error:", err));
} catch (error) {
console.log(error);
}
}
Actually am kinda disappointed as I tried many things and checked out many articles but non worked out for me.
function demo() {
console.log("Booooooooooooommmmmmmmmmm");
tokenV = document.getElementById("tokenString").value;
var urlF = "https://***********.com/connect/api.php?action=2&token="+tokenV;
const myHeaders = new Headers();
const myRequest = new Request(urlF, {
method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default',
});
fetch(myRequest)
.then(response => response.json())
.then(data => console.log(data));
}
I have already whitlist the domain inside my config file, am using phonegap CL latest version. I'm trying to connect to an api which will out put json.encode data if token were right.
Error output:
(index):50 Fetch failed loading: GET https://*******.com/connect/api.php.............
Another way I tried using cordova fetch plugin still failed:
function demo() {
console.log("Booooooooooooommmmmmmmmmm");
tokenV = document.getElementById("tokenString").value;
var urlF = "https://*********.com/api.php?action=2&token="+tokenV;
console.log("nowww1");
cordovaFetch(urlF, {
method : 'GET',
headers: {
'User-Agent': 'CordovaFetch 1.0.0'
},
})
.then(function(response) {
return response.json();
}).then(function(json) {
console.log('parsed json', json);
}).catch(function(ex) {
console.log('parsing failed', ex);
});
}
Error out put:
Error: exec proxy not found for :: FetchPlugin :: fetch (index):118 parsing failed TypeError: Network request failed
I can change the out put as I want but show me away to get the data from an external server???
Thank you
I am trying to debug the response from a post call. The post succeedes and the response is shown inside the response tab in the Chrome developer tools but the promise callback is never triggered.
Any idea why the callback is not triggered?
Here is the subscription:
this.mService.uploadFiles([file.name, new Blob()]).subscribe((response: any) => {
var myResponse = response;
//Do something with response
},
error => {
var err = `Failed with status = ${error.status}`;
});
Calling the Rest API:
public uploadFiles(files: any): Observable<any> {
let formData = new FormData();
formData.append('file', files[1], files[0]);
return this.http.post(`${this.myServiceEndpoint + "api/uploadFiles"}`, formData, {
observe: 'response'
}).pipe(map(response => response))
}
I am actually getting the following error even though the POST succeeds. Probable related to how the service is subscribing.
core.js:4002 ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (subscribeTo.js:28)
at subscribeToResult (subscribeToResult.js:15)
at CatchSubscriber.error (catchError.js:43)
at XMLHttpRequest.onLoad (http.js:1707)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:26247)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:498)
at invokeTask (zone.js:1693)
[UPDATE]
Below is the server side code for the called Azure Function
[FunctionName("UploadFiles")]
public async Task<IActionResult> UploadFiles([HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequest req, ILogger logger)
{
return (ActionResult)new OkObjectResult("Testing");
}
In this case Chrome displays the Testing string in the response tab. The callback is however not triggered.
... but if change the code to only return a OkResult the callback is triggered. So it seems the error appears only if the OkResult contains a payload. Any clue why this is failing?
return (ActionResult)new OkResult();
Give this a try do return response
public uploadFiles(files: any): Observable<any> {
let formData = new FormData();
formData.append('file', files[1], files[0]);
return this.http.post(`${this.myServiceEndpoint + "api/uploadFiles"}`, formData, {headers : new HttpHeaders({'Content-Type': 'application/x-www-form-urlencoded'})}).pipe(
map((response: Response) => {
return response;
})
)
}
whenever you do map in service like this do return that value so that mapped value will be return where you subscribing this service
EDIT
Try passing headers since you are passing file object in api
you can try like this
component
this.mService.uploadFiles([file.name, new Blob()]).subscribe((response: any) => {
var myResponse = response;
// here we are doing other operations like filtering and mapping etc..
myResponse.pipe(map(result => { console.log(result); }))
},
error => {
var err = `Failed with status = ${error.status}`;
});
service
public uploadFiles(files: any): Observable<any> {
let formData = new FormData();
formData.append('file', files[1], files[0]);
return this.http.post(`${this.myServiceEndpoint + "api/uploadFiles"}`, formData, {
observe: 'response'
});
}
Turns out I had to convert the response to json format on the server side (thought this was default json) and escaping the string quotes because the Angular interseptor was expecting json:
[FunctionName("UploadFiles")]
public async Task<IActionResult> UploadFiles([HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequest req, ILogger logger)
{
var jsonResponse = JsonConvert.SerializeObject("Testing");
return (ActionResult)new OkObjectResult(jsonResponse);
}
and the callback is triggered successfully.
So i am trying to make this post request, following aurelia docs:
http://aurelia.io/hub.html#/doc/article/aurelia/fetch-client/latest/http-services/3
And this is the request:
httpClient.configure(config => {
config
.withBaseUrl(baseUrl)
});
this.client = httpClient;
this.client.fetch(`/api/Register/${userName}`, {
method: "post",
body: json(loginInformation),
headers: {
'Access-Control-Allow-Origin' : '*',
'Accept': 'application/json'
}
}) .then(response => this.safelyParseJSON(response))
.then(data => this.setup(data));
where safetyParseJSON is:
safelyParseJSON(response) {
var parsed
try {
parsed = response.json();
} catch (e) {
}
return parsed
}
but i keep receiving this error:
"uncaught (in promise) SyntaxError: Unexpected end of JSON input"
Anyone have any idea on what am i doing wrong?
Note:
I am receiving this error only when receiving 404 / 500 from the server, if the results are ok, this works.
Note2: that i am wrapping this function inside try-catch but this still doesn't work, it doesn't catch the exception.
Note3: I have tried to replace this line:
parsed = response.json();
with this line:
parsed = JSON.parse(response);
But than the response is always undefined.
check the response's status prior to calling .json():
.then(response => {
if (response.ok) {
return response.json().then(data => this.setup(data));
}
return Promise.reject(response.text());
});
I ended up using Jeremy Danyow answer, with a small change:
.then(response => {
if (response.ok && response.status === 200) {
return response.json().then(data => this.setup(data));
}
return Promise.reject(response.text());
});
adding the response.status check was necessary in my case as response.ok was true for status code 204 (No content) aswell.