I am having problem with .stl file download in c# Angular JS MVC.
While the file is downloading I am not able to open the file in 3d shape or another software supporting stl file extension.
vm.FileDownload = function (id, hash,filename) {
var defer = $q.defer();
threeShapeRepo.getFile(id, hash, filename).then(function (data) {
if (data !== null) {
var file = new Blob([data], {
type: 'application/stl'
});
var fileURL = URL.createObjectURL(file);
var link = document.createElement('a');
link.href = fileURL;
link.target = '_blank';
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
//window.URL.revokeObjectURL(url);
defer.resolve(data);
});
}
From repository.js
function getFile(id, hash, fileName) {
var params = {
'Id': id,
'Hash': hash,
'FileName': fileName
}
var url = 'https://' + window.location.host + '/api/' + 'ThreeShape' + '/' + 'getFileAsync';
return $http.post(url, params, { responseType: 'blob' }).then(function (data) {
if (data.data.Content.indexOf("validation failed")!==-1) {
logError(data.data.Content);
return null;
}
return data.data;
});
}
In c# back end code:
public async Task<string> getFileAsyncInternal(GetFile request)
{
var response = new GetThreeShapeCasesResponse();
IList<GetOneThreeShapeCaseResult> tempCaseList = new List<GetOneThreeShapeCaseResult>();
IRestResponse restResponse;
var retryCount = 0;
HttpStatusCode statusCode;
int numericStatusCode;
var requestUrl = "";
InitializeThreeShapeClient();
var restRequest = new RestRequest(Method.GET);
if (request.Hash != null)
{
requestUrl = threeShapeServerLocation + "api/cases/"+ request.Id+"/attachments/"+ request.Hash;
}
ThreeShapeAPIClient.BaseUrl = new Uri(requestUrl);
var getTokenOperation = await retreive3ShapeBearerTokenInternal();
var myToken = getTokenOperation.TokenValue;
var tokenString = "Bearer " + myToken;
restRequest.AddHeader("Authorization", tokenString);
restResponse = ThreeShapeAPIClient.Execute(restRequest);
numericStatusCode = (int)restResponse.StatusCode;
System.Web.HttpResponse httpresponse = System.Web.HttpContext.Current.Response; ;
if (numericStatusCode == 200)
{
var strResult = restResponse.Content;
//return strResult;
string fileName = request.FileName;
httpresponse.ClearContent();
httpresponse.Clear();
byte[] buffer = new byte[restResponse.Content.Length];
System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
FileName = fileName,
Inline = true // false = prompt the user for downloading; true = browser to try to show the file inline
};
httpresponse.Headers.Add("Content-Disposition", "attachment;filename="+request.FileName+ ";filename*=UTF-8''" + request.FileName);
httpresponse.Headers.Add("Content-Length",Convert.ToString(restResponse.Content.Length));
httpresponse.Headers.Add("Contenty-Type", ((RestSharp.RestResponseBase)restResponse).ContentType);
httpresponse.Output.Write(restResponse.Content);
return restResponse.Content;
}
else if (retryCount == 0 && numericStatusCode == 401)
{
response.DidError = true;
response.ErrorMessage = restResponse.Content;
}
return restResponse.Content;
}
I have been struggling to make the downloaded file open. Any kind of help is deeply appreciated.
Response i am getting in content object is
I would start by comparing file contents of a clean copy and corrupt downloaded copy for clues. Is the downloaded copy really corrupt or is it actually empty? Do you see a pattern in the corrupt copies? etc Goodluck!
Related
I am trying to open a new tab and display a downloaded pdf from Core 2.2 web API in angular 9
public GeneratePdf(id: string): Observable<Blob> {
return this.http.get( this.urlPdf + '?id=' + id, { responseType: 'blob' });
}
this.dataProvider.GeneratePdf(id).subscribe({
next: (blob) => {
const blobpart = new Blob([blob], { type: 'application/pdf' });
var fileUrl = URL.createObjectURL(blobpart);
let win: any = this.getWindow();
win.open(fileUrl);
},
error: (err) => this.error.handelHttpError(err),
});
API
[HttpGet]
[Route("PDF")]
public async Task<HttpResponseMessage> PDF(Guid Id) {
_logger.LogInformation("Request:" + Request.GetDisplayUrl());
var endpoint = _appSettings.PdfEndpoint;
try {
var param = await _dal.GetPDFParameters(Id, endpoint);
// Get PDF stream
HttpResponseMessage response = await client.GetAsync(param.EndpontUrl);
if(response.IsSuccessStatusCode) {
using(HttpContent content = response.Content) {
var memStream = new MemoryStream();
Stream sourceStream = await content.ReadAsStreamAsync();
sourceStream.CopyTo(memStream);
var result = new HttpResponseMessage(HttpStatusCode.OK) {
Content = new ByteArrayContent(memStream.ToArray())
};
result.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") {
FileName = Id.ToString() + ".pdf"
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
} else {
var result = new HttpResponseMessage(HttpStatusCode.BadRequest);
return result;
}
} catch(Exception ex) {
_logger.LogError(ex, "Exception error");
var result = new HttpResponseMessage(HttpStatusCode.InternalServerError);
return result;
}
}
it doesn't throw an error, it just opens a json object in the new tab, and the size of the object looks too small as the pdf content is over 3k bytes
{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[{"key":"Content-Disposition","value":["attachment; filename=bd94ee98-65be-4c4f-a001-abecaf1a0644.pdf"]},{"key":"Content-Type","value":["application/octet-stream"]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"requestMessage":null,"isSuccessStatusCode":true}
update, there was a small error on the Blob, I was not passing in the blobpart to the url.CreateObjecturl Now the app loads the new tab, but states an invalid pdf as there is no content. I know the pdf bytes are going into the content of the api result as i have checked it. and converted it to a string to ensure it's a pdf, which it is.
Thanks for taking the time too look.
I am trying to post one or more files from my local machine to an API with HttpClient, MultipartFormContent and ContentType: "application/octet-stream" but when i do postSync and call an API from a local Winform application, the result of the task (var response = task.Result;) says that it is "Unsopported Type File" StatusCode: 415. I tried with ByteArrayContent but was still unsuccessful.
This is my code:
bool Upload(string url, string path, string localFilename, string fileName, string projectId, string folderId)
{
Boolean isFileUploaded = false;
string xapiKey = "-----";
try
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(url);
httpClient.DefaultRequestHeaders.Add("x-api-key", xapiKey);
var fileInfo = new FileInfo(localFilename);
FileUpload uploadResult = null;
bool _fileUploaded = false;
//Extract content file
FileStream fileStream = File.OpenRead(path);
var streamContent = new StreamContent(fileStream);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
streamContent.Headers.ContentDisposition.FileName = "\"" + Path.GetFileName(path) + "\"";
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octetstream");
string boundary = Guid.NewGuid().ToString();
MultipartFormDataContent content = new MultipartFormDataContent(boundary);
content.Headers.Remove("Content-Type");
content.Headers.TryAddWithoutValidation("Content-Type", "mulitpart/form-data; boundary=" + boundary);
content.Add(streamContent);
//content.Add(new StreamContent(fileStream), "\"file\"", string.Format("\"{0}\"", fileName + fileInfo.Extension));
Task taskUpload = httpClient.PostAsync(url, content).ContinueWith(task =>
{
if (task.Status == TaskStatus.RanToCompletion)
{
var response = task.Result;
if (response.IsSuccessStatusCode)
{
uploadResult = response.Content.ReadAsAsync<FileUpload>().Result;
if (uploadResult != null)
_fileUploaded = true;
}
}
fileStream.Dispose();
});
taskUpload.Wait();
if (_fileUploaded)
isFileUploaded = true;
httpClient.Dispose();
}
catch (Exception ex)
{
isFileUploaded = false;
throw new Exception(ex.Message);
}
return isFileUploaded;
}
I am uploading a file to webapi which saves a file(pdf's & word documents) to mongodb gridfs(v 2.6.1)
webapi code
var file = Request.Files[0];
var fileName = file.FileName;
var fileType = file.ContentType;
var document = blabl.UploadFile(fileName, fileType,ReadFully(file.InputStream));
convert incoming stream to bytes
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
GridFs code
var bucket = new GridFSBucket(_database, new GridFSBucketOptions
{
BucketName = bucketName,
WriteConcern = WriteConcern.WMajority,
ChunkSizeBytes = 1048576
});
var id = bucket.UploadFromBytes(fileName, source, options);
return id;
Code to download
var bucket = new GridFSBucket(_database, new GridFSBucketOptions
{
BucketName = bucketName
});
return bucket.DownloadAsBytes(id);
WebApi
HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(data);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "MyPdf.pdf"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return result;
UI code
$.ajax({
url:'path',
type: 'GET',
responseType: 'arraybuffer',
success: function (data)
{
var link = document.createElement('a');
if ('download' in link)
{
try {
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute("download", filename);
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
} catch (ex)
{
console.log(ex);
}
}
}
});
Post download the file is empty.
I would be really greatfull if you guys point me in the right direction.
i had changed the webapi code as below
HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
httpResponseMessage.Content = new ByteArrayContent(data.ToArray());
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
httpResponseMessage.StatusCode = HttpStatusCode.OK;
return httpResponseMessage;
Also, i forgot that i had a delegating handler which is changing the response.
I'm working on UWP apps, In that i need to upload the image for that i'm calling the web service to post the details. I'm using the below code to serialize the image.
byte[] fileBytes = null;
using (var stream = await file.OpenReadAsync())
{
fileBytes = new byte[stream.Size];
using (var reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(fileBytes);
}
}
docs.Document = fileBytes;
docs.DocumentName = file.Name;
docs.DocumentTypeOtherDescription = "ProfilePicture";
var docsAsJson = JsonConvert.SerializeObject(docs);
StringContent stringContent = new StringContent(docsAsJson, System.Text.Encoding.UTF8);
ByteArrayContent byteContent = new ByteArrayContent(fileBytes);
MultipartFormDataContent httpContent = new MultipartFormDataContent();
httpContent.Add(byteContent, file.Name);
httpContent.Add(stringContent);
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage {Method = HttpMethod.Post};
request.Headers.Add("authorization", App.TokenType + " " + App.AccessToken);
request.RequestUri = new Uri(App.BaseUrl + "api/User/UploadUserDocument");
request.Content = httpContent;
request.Content.Headers.Add(#"Content-Length", fileBytes.Length.ToString());
var response = httpClient.SendAsync(request).Result;
var data = response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
}
}
This is my side to serialize the image and in service side they deserialize the image and saved in database. But i'm getting StatusCode: 500, ReasonPhrase: 'Internal Server Error' this error, Any one please help me to solve this issue.
Here is my Service Code:
public IHttpActionResult UpdateUserWithProfilePic(FormData userviewmodel)
{
var error = string.Empty;
var userJson = new StringBuilder();
foreach (var items in userviewmodel.Fields)
{
if (items.Name == "}")
{
if (!userJson.ToString().EndsWith(",")) continue;
userJson.Remove(userJson.Length - 1, 1);
userJson.Append("}");
}
else
userJson.Append((items.Name.Replace("%22", "\"")) + ":" + items.Value);
}
var userView = JsonConvert.DeserializeObject<UserViewModel>(userJson.ToString());
var result = UpdateUser(userView, error);
if (result.ResultType != ResultType.Success) return daHttpActionResult(result.Result, result);
if (userviewmodel.Files != null && userviewmodel.Files.Count > 0)
{
userView.ProfileDocument = new UserDocument
{
DocumentName = userviewmodel.Files[0].Name,
Document = userviewmodel.Files[0].Value.Buffer,
UserID = UserId,
DocumentType = DocumentTypeEnum.ProfilePicture,
DocumentTypeOtherDescription = userviewmodel.Files[0].Value.MediaType,
};
}
return AdHttpActionResult(result.Result, result);
}
Thanks & Regards,
Cristina
I've got a server method that takes and codifies a list of strings, since IE9 doesn't read json format, what I want is to set the string in the content of an http response message. I seems to do it well but when I get the response I can's find the response on the body, what I can see is only the length of what I set in the response message.
here is the code:
public HttpResponseMessage Upload()
{
HttpResponseMessage m = new HttpResponseMessage(HttpStatusCode.OK);
List<string> returnlist = new List<string>();
for (int i = 0; i < Request.Files.Count; i++)
{
//string treatment
}
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StringContent(string.Join(",", returnlist));
return response;
}
this is what the string contains "file1,file2,file3"
but I can't find it debugging in visual studio or firebug
The response that I get is:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Content-Type: text/plain; charset=utf-8
}
How can I set and then get the response message?
In case of need the js here is it:
self.uploadfiles = function () {
//startSpinner();
if (!self.isOldIE()) {
var loc = window.location;
base_url = loc.protocol + "//" + loc.host;
baseUrl = base_url + "/";
var save = true;
var xhr = new XMLHttpRequest();
xhr.open('POST', baseUrl + 'Home/Upload');
xhr.send(formdata);
xhr.onreadystatechange = function (data) {
//The responseText is the same as above
if (xhr.responseText.length > 0) {
//do stuff
}
};
Try this code
var response = Request.CreateResponse(HttpStatusCode.OK, string.Join(",", returnlist));
return response;
Try this to get the response using Javascript:
var xhr = new XMLHttpRequest();
xhr.open('POST', baseUrl + 'Home/Upload', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
alert(xhr.responseText);
} else {
// do something about the error
}
};
xhr.send(formdata);
Note the third boolean parameter of the open() method for getting asynchronously.
For some reason the browsers doesn't show the entire body of the http response. So my solution was to write the header of the response and get the header from js.
Maybe somebody knows why the browsers doesn't show the body, or has a better solution.
This is my controller:
public HttpResponseMessage Upload()
{
HttpResponseMessage m = new HttpResponseMessage(HttpStatusCode.OK);
List<string> returnlist = new List<string>();
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i]; //Uploaded file
//Use the following properties to get file's name, size and MIMEType
int fileSize = file.ContentLength;
if (file.FileName != "")
{
string fileName = string.Format("{0}.{1}", Guid.NewGuid().ToString(), file.FileName.ToString().Split('.')[1].ToString());
returnlist.Add(fileName);
}
}
//Here I write the response message headers
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StringContent(string.Join(",", returnlist), Encoding.UTF8, "text/html");
response.Headers.Add("data", string.Join(",", returnlist));
return response;
}
And here is how I get the header response:
var xhr = new XMLHttpRequest();
xhr.open('POST', baseUrl + 'Home/Upload');
xhr.send(formdata);
xhr.onreadystatechange = function (data) {
if (xhr.responseText.length > 0) {
//header response
var response = xhr.responseText;
}