I am trying to pass a file from S3 directly into the users' download stream like this:
public HttpResponseMessage Download()
{
var result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new MemoryStream();
using (var client = new AmazonS3Client(RegionEndpoint.USWest2))
{
var request = new GetObjectRequest
{
BucketName = "bucket",
Key = "filename"
};
using (var response = client.GetObject(request))
{
response.ResponseStream.CopyTo(stream);
}
}
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "file.pdf"
};
return result;
}
But the file downloads as 0 bytes. I assumed that the file is completely loaded in memory on line ResponseStream.CopyTo.
Related
can I set a post method to post image and list of object in the same time I have the following code it's logically working but I'm trying to test this request with postman
private ApplicationDbContext1 db = new ApplicationDbContext1();
[Route("api/save_BUY")]
[HttpPost]
public async Task< IHttpActionResult> save_BUY(IEnumerable<BY_table> BY_table,int id)
{
var BY_API = BY_table.Select(p => new BY_API
{
ITEM_CODE = p.ITEM_CODE,
ITEM_NAME = p.ITEM_NAME,
Unit = p.Unit,
Unit_Core = Convert.ToDecimal(p.Unit_Core),
}).AsQueryable();
var ctx = HttpContext.Current;
var root = ctx.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.FileData)
{
var name = file.Headers
.ContentDisposition
.FileName;
var localFileName = file.LocalFileName;
var filePath = Path.Combine(
root, "files", name);
byte[] fileBytes;
using (var fs = new FileStream(
PHOTO, FileMode.Open, FileAccess.Read))
{
fileBytes = new byte[fs.Length];
fs.Read(
fileBytes, 0, Convert.ToInt32(fs.Length));
}
var MASTER_BUY = db.MASTER_BUY.Where(x => x.int==id)
{
MASTER_BUY.image= fileBytes;
};
db.SaveChanges();
return Ok(BY_API);
}
}
how can I make this request in postman to test it.
pleas help.
You Can send Image Form of base64 String And Get String value from Client(Postman)
Image to Base 64 String
This is one Of Online tools for help you get base 64 string from file!
I am using the below code to create and download a Telerik report.
var reportName = "../api/Templates/Invoice.trdp";
var reportProcessor = new Telerik.Reporting.Processing.ReportProcessor();
var reportSource = new Telerik.Reporting.UriReportSource()
{
Uri = reportName
};
reportSource.Parameters.Add("ID", 3);
reportSource.Parameters.Add("Username", "demouser");
var deviceInfo = new System.Collections.Hashtable()
{
{"DocumentTitle", "Annual Report" }
};
var result = reportProcessor.RenderReport("PDF", reportSource, deviceInfo);
if (!result.HasErrors)
{
System.IO.File.WriteAllBytes(System.IO.Path.ChangeExtension(reportName, "pdf"), result.DocumentBytes);
}
}
Once I host it in a server, it creates the file in the server side. How can I download it into the client machine without creating any files in the server.
I was able to do it by returning the file back to the client using the return type HttpResponseMessage
public HttpResponseMessage GenerateOrderReport(int orderID)
{
var reportName = ConfigurationManager.AppSettings["EmailAttachmentURLTemplate"];
string activeDir = ConfigurationManager.AppSettings["EmailAttachmentSaveLocation"];
string newPath = System.IO.Path.Combine(activeDir, ConfigurationManager.AppSettings["EmailAttachmentSaveFolder"]);
var reportProcessor = new Telerik.Reporting.Processing.ReportProcessor();
var reportSource = new Telerik.Reporting.UriReportSource()
{
Uri = reportName
};
reportSource.Parameters.Add("OrderID", 141);
reportSource.Parameters.Add("OrderMethodTypeID", 2);
var deviceInfo = new System.Collections.Hashtable()
{
{"DocumentTitle", "Order Report" }
};
var result = reportProcessor.RenderReport("PDF", reportSource, deviceInfo);
if (!result.HasErrors)
{
System.IO.Directory.CreateDirectory(newPath);
string newFileName = "OrderReport.pdf";
newPath = System.IO.Path.Combine(newPath, newFileName);
FileStream fileStream = new FileStream(newPath, FileMode.Create, FileAccess.ReadWrite);
fileStream.Write(result.DocumentBytes, 0, result.DocumentBytes.Length);
fileStream.Close();
HttpResponseMessage fileResult = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(newPath, FileMode.Open);
fileResult.Content = new StreamContent(stream);
fileResult.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
fileResult.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
fileResult.Content.Headers.ContentDisposition.FileName = newFileName;
return fileResult;
}
else
{
throw new Exception("Report contains errors. " + result.Errors[0].Message);
}
}
I need upload image to server using api.
Now I'm using System.Net.Http;
byte[] lFileBytes= DependencyService.Get<IFileHelper>().ReadAllBytes(ImagePath);
ByteArrayContent lFileContent = new ByteArrayContent(lFileBytes,0,lFileBytes.Length);
lFileContent.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse("form-data");
lFileContent.Headers.ContentType=new MediaTypeHeaderValue("image/jpg");
lFileContent.Headers.ContentDisposition.Parameters.Add(new NameValueHeaderValue("name","file"));
lFileContent.Headers.ContentDisposition.Parameters.Add(new NameValueHeaderValue("filename", "9.jpg"));
lFileContent.Headers.ContentLength= lFileBytes.Length;
lContent.Add(lFileContent);
public byte[] ReadAllBytes(string path) {
using (var streamReader = new StreamReader(path))
{
using (var memoryStream = new MemoryStream())
{
streamReader.BaseStream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
}
After sending request i have error Type file is invalid
I'm thinking problem in byte[] ReadAllBytes(string path)
For request i can use Stream or byte[]
Please, help
UPDATE
lRequestResponse = await lHttpClient.PostAsync("URL", lContent);
In case you still need, this works for me:
var cont = new MultipartFormDataContent();
var image = new StreamContent(img.Image.GetStream());
cont.Add(image, "\"file\"", img.FileName);
var uri = App.apiurl + $"FileUpload/" + img.FileName + "/";
using (var client = new HttpClient())
{
var response = await client.PostAsync(uri, cont);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
// return error code
}
}
This help me
MultipartFormDataContent lContent=new MultipartFormDataContent();
byte[] lBytes = DependencyService.Get<IFileHelper>().ReadAllBytes(filename);
ByteArrayContent lFileContent= new ByteArrayContent(lBytes);
lFileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
FileName = filename,
Name = "imgFile"
};
lFileContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
lContent.Add(lFileContent);
HttpResponseMessage lRequestResponse=await lHttpClient.PostAsync(await url, lContent);
IFileHelper implement on IOS
namespace Client.iOS
{
public class FileHelper : IFileHelper
{
private string GetLocalFilePath(string filename)
{
string docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string libFolder = Path.Combine(docFolder, "..", "images", "Databases");
if (!Directory.Exists(libFolder))
{
Directory.CreateDirectory(libFolder);
}
return Path.Combine(libFolder, filename);
}
public byte[] ReadAllBytes(string filename)
{
string path=GetLocalFilePath(filename);
return (FileStream(path) as MemoryStream).ToArray();
}
private Stream FileStream(string path)
{
StreamReader lStreamReader = new StreamReader(path);
MemoryStream lMemoryStream = new MemoryStream();
lMemoryStream.Position = 0;
lStreamReader.BaseStream.CopyTo(lMemoryStream);
return lMemoryStream;
}
}
}
I have created WebAPI which returns an excel file using closedxml nuget. Basically it converts my DataTable to excel. I'm referring couple of links below,
How to return a file (FileContentResult) in ASP.NET WebAPI
Returning binary file from controller in ASP.NET Web API
Issue : excel generated on server path has NO issues. But when I download the same by returning it as HttpResponseMessage via webAPI the excel file is corrupted. It says, "The file is corrupt and cannot be opened" :(
My Code :
[System.Web.Http.AcceptVerbs("GET", "POST")]
public HttpResponseMessage ExportExcel()
{
DataTable scoredRecords = Getdt();
if (scoredRecords.Rows.Count > 0)
{
var path = #"C:\Raghav\asdf.xlsx";
XLWorkbook wb = new XLWorkbook();
wb.Worksheets.Add(scoredRecords, "sample");
// excel getting generated on server properly-No issues.
wb.SaveAs(path);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(path, FileMode.Open);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "sample.xlsx"
};
result.Content.Headers.ContentLength = stream.Length;
//tried with "application/ms-excel" also
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
}
The generated excel on server has no issues. Only the downloaded excel file via webAPI is corrupted. Unable to figure out the issue..
any help appreciated!! :)
Try this:
[HttpGet]
public HttpResponseMessage Export()
{
using (var wb = new XLWorkbook())
using (MemoryStream ms = new MemoryStream())
{
wb.Worksheets.Add("sample").FirstCell().SetValue("some value");
wb.SaveAs(ms);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(ms.GetBuffer());
result.Content.Headers.ContentLength = ms.Length;
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "sample.xlsx"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;
}
}
One issue I am seeing is that :
var stream = new FileStream(path, FileMode.Open);
you are sending FileStream. Instead of this, you can try with byte [] :
byte[] excelData = File.ReadAllBytes(path);
result.Content = new StreamContent(excelData);
You can give a try with this.
My webapi method for zipping on the fly use this code
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new PushStreamContent((stream, content, arg3) =>
{
using (var zipEntry = new Ionic.Zip.ZipFile())
{
using (var ms = new MemoryStream())
{
_xmlRepository.GetInitialDataInXml(employee, ms);
zipEntry.AddEntry("content.xml", ms);
zipEntry.Save(stream); //process sleep on this line
}
}
})
};
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "FromPC.zip"
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
I want to
1) take data from _xmlRepository.GetInitialDataInXml
2) zip data on the fly via Ionic.Zip
3) return zipped stream as output of my WebApi action
But on this line zipEntry.Save(stream); execution process stops and don't go to next line. And method don't return anything
So why it doesnt' return me file?
When using PushStreamContent, you would need to close the stream to signal that you are done writing to the stream.
Remarks section in the documentation:
http://msdn.microsoft.com/en-us/library/jj127066(v=vs.118).aspx
The accepted answer is not correct. It is not necessary to close the stream if you want to start streaming. The streaming starts automatically (download dialog in browser) when the delegated function ends. In case of big files OutOfMemoryException is thrown, but it is handled and the streaming begins -> HttResponseStream is flushed towards the client.
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new PushStreamContent(async (outputStream, httpContext, transportContext) =>
{
using (var zipStream = new ZipOutputStream(outputStream))
{
var employeeStream = _xmlRepository.GetEmployeeStream(); // PseudoCode
zipStream.PutNextEntry("content.xml");
await employeeStream.CopyToAsync(zipStream);
outputStream.Flush();
}
});
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "FromPC.zip" };
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;