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.
Related
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!
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.
This code is supposed to result in a file download...
public HttpResponseMessage Export()
{
var byteArray = Encoding.UTF8.GetBytes("Hello World!");
var stream = new MemoryStream(byteArray);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(stream),
};
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "myFile.csv"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
return result;
}
Instead I get this message...
{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[]},"statusCode":200,"reasonPhrase":"OK","headers":[],"requestMessage":null,"isSuccessStatusCode":true}
What am I doing wrong?
public IActionResult Export()
{
var byteArray = Encoding.UTF8.GetBytes("Hello World!");
var stream = new MemoryStream(byteArray);
return File(stream, "myFile.csv", "text/csv");
}
I'm trying to download a closedXml excel file in a webapi/angularjs application.
I'm returning the data from the webapi controller on the server using:
HttpResponseMessage result = new HttpResponseMessage();
result = Request.CreateResponse(HttpStatusCode.OK);
MemoryStream stream = GetStream(workbook);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Download.xlsx"
};
return result;
and then saving it on the client using:
$scope.openExcel = function (data, status, headers, deferred) {
var type = headers('Content-Type');
var disposition = headers('Content-Disposition');
if (disposition) {
var match = disposition.match(/.*filename=\"?([^;\"]+)\"?.*/);
if (match[1])
defaultFileName = match[1];
}
defaultFileName = defaultFileName.replace(/[<>:"\/\\|?*]+/g, '_');
var blob = new Blob([data], { type: type });
saveAs(blob, defaultFileName);
Excel says the file is in a different format than specified by the extension and then doesn't open properly.
On projects I work on, I make a Controller for files(not an ApiController)
public class FilesController : Controller
{
public FileResult GetFile(/*params*/)
{
// get fileBytes
var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
return base.File(fileBytes, contentType, "Download.xlsx");
}
}
and then from angular, I open the file like this
$window.open("/Files/GetFile/" /*+ params*/);
I just want to return a .csv file.
It works with the HttpResponseMessage but not with IHttpActionResult
Why?
WORKS
public async Task<HttpResponseMessage> ExportLeads()
{
byte[] bytes = new byte[2];
var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(bytes) };
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "test.csv" };
return result;
}
DOES NOT WORK
public async Task<IHttpActionResult> ExportLeads()
{
byte[] bytes = new byte[2];
var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(bytes) };
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "test.csv" };
return Content(HttpStatusCode.OK, result);
}
Error =>
The type "System.Net.Http.ByteArrayContent" can not be serialized.
Annotate it with the Attribut "DataContractAttribute"...
Content(HttpStatusCode.OK, result) will return a NegotiatedContentResult. As such you will need to set up a ContentNegotiator and Formatters to format the file contents. As you just want to return the raw CSV as a binary array in the content (as per your code returning HttpResponseMessage) then you should use the following:
return this.ResponseMessage(result)