Image gets corrupted after FileUpload with FtpWebRequest - file-upload

I have a code that uploads an image. I use await/async. The code do upload .txt files and .jpg files for example.
However, when uploading a .jpg image. It does get uploaded. However when I download it from the server manually to my desktop(using FileZilla), I can't open the file in paint. I get this error:
Paint cannot read this file. This is not a valid bitmap file, or its format is not currently supported
Other Information:
Original Filesize: 109 309 bytes
When Uploaded to server: 109 308 bytes
void uploadimage()
{
String sourceimage = "C:/ESD/image_2.jpg";
Task<bool> task = FtpUploadFile(sourceimage);
if (task.IsFaulted == false)
{
MessageBox.Show(task.Result.ToString());
}
}
private Task closeRequestStreamAsync(Stream requestStream) { return Task.Run(() => { requestStream.Close(); }); }
public async Task<bool> FtpUploadFile(string filename)
{
//if exception occurs we want to be able to close these
FtpWebResponse response = null;
FtpWebRequest request = null;
FileStream sourceStream = null;
Stream requestStream = null;
try
{
bool isimage = false; String ext = Path.GetExtension(filename);
if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".bmp") { isimage = true; }
request = (FtpWebRequest)WebRequest.Create("ftp://someurl.com/Folder1/test1.jpg");
request.UsePassive = true;
if (isimage == true) { request.UseBinary = true; } //for images
if (isimage == false) { request.UseBinary = false; } //for text
request.KeepAlive = true; //keep the connection open
request.Method = WebRequestMethods.Ftp.UploadFile;
request.ConnectionGroupName = "Group1";
request.ServicePoint.ConnectionLimit = 4;
//These are the credentials.
request.Credentials = new NetworkCredential("username", "password");
sourceStream = File.OpenRead(filename);
byte[] buffer = new byte[sourceStream.Length];
await sourceStream.ReadAsync(buffer, 0, buffer.Length);
sourceStream.Close();
requestStream = await request.GetRequestStreamAsync();
await requestStream.WriteAsync(buffer, 0, buffer.Length);
//MPM This is the call that takes the time
await closeRequestStreamAsync(requestStream);
//response = (FtpWebResponse)request.GetResponse();
WebResponse responseWeb = await request.GetResponseAsync();
response = (FtpWebResponse)responseWeb;
if (response.StatusDescription.Contains("226"))
{
//This means that we successfully have uploaded the file!
}
response.Close();
return true;
}
catch (Exception ex)
{
string errMSG = string.Format("Upload File failed, exception: {0}", ex.Message);
return false;
}
}

I did forget to add this to my code so images do use binary for images. Now it works:
if (isimage == true) { request.UseBinary = true; } //for images
if (isimage == false) { request.UseBinary = false; } //for text

Related

Retreive the file name and size uploaded via postman in asp.net core

I have tried the following code ..
When I try out the following code I get 404 content not found. Also my controller doesn't get hit when I try to debug the code ..
public async Task<IActionResult> Download(string filename)
{
if (filename == null)
return Content("filename not present");
var path = Path.Combine(Directory.GetCurrentDirectory(),"wwwroot", filename);
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, GetContentType(path), Path.GetFileName(path));
}
Upload file with size and filename as response:
public async Task<IActionResult> OnPostUploadAsync(IFormFile file)
{
long size = file.Length;//in bytes
if (file.Length > 0)
{
var name = Path.GetRandomFileName();
//var fileOriginName = file.FileName;
var path = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot", name);
using (var stream = System.IO.File.Create(path))
{
await file.CopyToAsync(stream);
}
return Ok(new { size = size, filename = name });
}
else {
return Ok(new { size = 0, filename = ""});
}
}
===============================================
I have an api like below and I had a file test.txt in wwwroot folder.
public async Task<IActionResult> Download(string filename)
{
if (filename == null)
return Content("filename not present");
var path = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot", filename);
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
var contentType = "APPLICATION/octet-stream";
return File(memory, contentType, Path.GetFileName(path));
}
Then when I call localhost:port/home/download?filename=test then I'll get exception that file can't find. And when I call localhost:port/home/Download?filename=test.txt it succeeds.
My API is in an asp.net core MVC project and I think you need to check the contentType.

ASP .Net Core file upload - getting form data when [DisableFormValueModelBinding] attribute is in place

I went ahead and implemented an ASP .Net Core file upload controller per the documentation and it requires using a [DisableFormValueModelBinding] attribute for streaming large files. I got that working fine. Unfortunately, when using that attribute it seems to block my JSON properties coming in from the form.
Is there any way to get both the file and the form data here? Here is my controller code (the request.form calls are where I am having issues):
[Route("{caseNbr:int}/Document")]
[ResponseType(typeof(CaseDocumentModel))]
[DisableFormValueModelBinding]
[HttpPost]
public async Task<IActionResult> PostDocument(int caseNbr)
{
string errorTrackingFileName = string.Empty;
try
{
UserSessionModel userSessionModel = SessionExtensions.CurrentUserSession;
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
return BadRequest("Bad Request");
}
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
if (!MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
{
return BadRequest("Bad Request");
}
var fileName = WebUtility.HtmlEncode(contentDisposition.FileName.Value);
errorTrackingFileName = fileName;
var trustedFileNameForFileStorage = fileName; //Path.GetRandomFileName();
var streamedFileContent = await FileHelpers.ProcessStreamedFile(section, contentDisposition, ModelState, _permittedExtensions, _fileSizeLimit);
if (!ModelState.IsValid)
{
return BadRequest("Bad Request");
}
using (var targetStream = System.IO.File.Create(Path.Combine(_tempFilePath, trustedFileNameForFileStorage)))
{
await targetStream.WriteAsync(streamedFileContent);
**//This is where I am having trouble:**
string descrip = HttpContext.Request.Form["Description"].ToString();
string docType = HttpContext.Request.Form["DocType"].ToString() ?? "Document";
bool isGeneralFileUpload = false;
if (string.IsNullOrWhiteSpace(Request.Form["GeneralFileUpload"]) == false && AppHelper.IsBool(Request.Form["GeneralFileUpload"]))
isGeneralFileUpload = bool.Parse(Request.Form["GeneralFileUpload"]);
int transcriptionJobId = 0;
if (string.IsNullOrWhiteSpace(Request.Form["TranscriptionJobId"]) == false && AppHelper.IsNumeric(Request.Form["TranscriptionJobId"]))
transcriptionJobId = int.Parse(Request.Form["TranscriptionJobId"]);
CaseDocumentModel createdCaseDocumentModel;
if (docType.Equals("Dictation"))
createdCaseDocumentModel = DictationRepository.ProcessDictationFile(userSessionModel.DBID, caseNbr, _tempFilePath, fileName, userSessionModel);
else if (isGeneralFileUpload)
createdCaseDocumentModel = DashboardAdjusterRepository.CreateGeneralFileUploadDocument(_tempFilePath, fileName, userSessionModel, docType, descrip);
else if (docType.Equals("Transcription"))
createdCaseDocumentModel = TranscriptionRepository.UploadTranscriptionFile(userSessionModel.DBID, _tempFilePath, fileName, userSessionModel, transcriptionJobId);
else
createdCaseDocumentModel = CaseRepository.CreateCaseDocumentRecord(userSessionModel.DBID, caseNbr, descrip, docType, _tempFilePath, fileName, userSessionModel);
return Ok(createdCaseDocumentModel);
}
}
// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
}
catch (Exception ex)
{
AppHelper.WriteErrorLog("CaseController PostDocument failed due to " + ex.Message + " case number was " + caseNbr + " file name was " + errorTrackingFileName);
return BadRequest("Bad Request");
}
return BadRequest("Bad Request");
}
Here is a sample call with Postman:
Screen shot of Postman

Get Array of Bytes from ASP.NET WEB API to be rendered in PDF using React/Redux

I have this action on my WEBAPI´s controller using .NET that returns bytes from SSRS report link:
public IHttpActionResult GetReport(int? Id)
{
if (Id == null)
{
return NotFound();
}
var reportServer = ConfigurationManager.AppSettings["Report"];
var reportPath = $"{reportServer}/myReport&Id={Id}&rs:Format=PDF";
WebClient Client = new WebClient();
Client.UseDefaultCredentials = true;
byte[] reportBytes = Client.DownloadData(reportPath);
var reportBase64 = Convert.ToBase64String(reportBytes);
return Ok(reportBase64);
}
When i try to generate the PDF from this return, using this react/redux code ( i am using axios)....
//...code
const reportBlob = new Blob([myReportData], { type: "application/pdf" });
const reportBlobUrl = URL.createObjectURL(reportBlob);
window.open(reportBlobUrl);
.....it oppened a new browser´s tab with PDF template BUT showing PDF Error as: 'FAILED TO LOAD PDF document'.
No anwsers anywhere help me resolving this problem. :(
Note: the 'axios' call it´s returning the same array of bytes as the WEBAPI return, so as the 'myReportData' variable.
So i figured out by my self after 4 days. Anyone that needed this functionality (render the SSRS report in PDF within c# code returning PDF bytes from a ASP.NET WEB API, here is the what you have to do within your webapi controller to generate the PDF bytes from report viewer namespace to be sent to your React app using Redux.
WEB API ASP.NET (.NET Framework 4.6 using VS 2019):
note: first option i´ts commented and works the same way the option 2 that i´d prefer.
// return type is Bytes
[HttpGet]
[Route("api/YourReport/{testId}")]
public async Task<IHttpActionResult> GetYourReportAsync(int? testId)
{
if (testId == null)
{
return NotFound();
}
try
{
// 1. Works in this way without '?' on the end of the URL
// URL should be like this: "http://-yourServerName-/reportserver/ReportExecution2005.asmx"
//ReportExecutionService rs = new ReportExecutionService();
//rs.Credentials = CredentialCache.DefaultCredentials;
//rs.Url = "http://-yourServerNamein here-/reportserver/ReportExecution2005.asmx";
//// Render arguments
//byte[] result = null;
//string reportPath = "/-yourReportsFolderName-/-yourReportName-";
//string format = "PDF";
//string historyID = null;
//string devInfo = #"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
//// parameters
//ParameterValue[] parameters = new ParameterValue[1];
//parameters[0] = new ParameterValue();
//parameters[0].Name = "yourId";
//parameters[0].Value = testId.ToString();
//string encoding;
//string mimeType;
//string extension;
//Warning[] warnings = null;
//string[] streamIDs = null;
//ExecutionInfo execInfo = new ExecutionInfo();
//ExecutionHeader execHeader = new ExecutionHeader();
//rs.ExecutionHeaderValue = execHeader;
//execInfo = rs.LoadReport(reportPath, historyID);
//rs.SetExecutionParameters(parameters, "en-us");
//string SessionId = rs.ExecutionHeaderValue.ExecutionID;
//try
//{
//// result type is bytes
// result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
//}
//catch (SoapException)
//{
// throw;
//}
//// below, just in case that you want to save it locally in PDF format.
//try
//{
// FileStream stream = File.Create(#"c:\report.pdf", result.Length);
//
// stream.Write(result, 0, result.Length);
// Console.WriteLine("Result written to the file.");
// stream.Close();
//}
//catch (Exception)
//{
// throw;
//}
//return await Task.Run(() => Ok(result));
// 2. Works this way also with '?' on the end of the URL
// URL should be like this: "http://-yourServerName-/reportserver/ReportExecution2005.asmx?"
using (ReportViewer yourReportViewer = new ReportViewer())
{
yourReportViewer.ProcessingMode = ProcessingMode.Remote;
// get the values from your web.config.
yourReportViewer.ServerReport.ReportServerUrl = new Uri(ConfigurationManager.AppSettings["youtReport"]);
yourReportViewer.ServerReport.ReportPath = $"/yourReportsFolder/yourReport";
;
ReportParameter testPlanIdParameter = new ReportParameter();
testPlanIdParameter.Name = "yourId";
testPlanIdParameter.Values.Add(testId.ToString());
yourReportViewer.ServerReport.SetParameters(new ReportParameter[] { testIdParameter });
byte[] yourReportBytes = yourReportViewer.ServerReport.Render("PDF");
return await Task.Run(() => Ok(yourReportBytes));
}
}
catch (SoapException)
{
throw;
}
catch (Exception)
{
throw ;
}
}
REACT/REDUX nstrong textote: you have to convert the stream of bytes returned from your WEB API Controller into BLOB format to render it in a new brownser tab in PDF format/type.
a. the button action/behavior
<div className="btn-group-vertical" role="group">
<button className="btn btn-sm btn-success ml-2 mb-2" style={{ width: '160px' }} onClick={(e) => openReport(e, testId)}>
<i className="fas fa-print"></i>
Report
</button>
</div>
b. the component ( i am omiting the redux part (reducers, actions, apiservice...)
openReport(event, item) {
event.preventDefault();
this.props.actions.loadReport(item);
this.setState({ Report: this.props.Report });
const ReportData = this.state.Report;
const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return blob;
}
const ReportBlob = b64toBlob(ReportData, 'application/pdf');
const ReportBlobUrl = URL.createObjectURL(ReportBlob);
window.open(ReportBlobUrl);
}

Win Phone 8.1 : OutOfMemory Exception while downloading large files (30 MB)

I am creating a universal Windows Phone 8.1 App. I am trying to download the file and view it into launcher. I works for small file less than 15 MB files. But when file size is more than 15 MB, I got the out of memory exception.
async private Task<object> GetMailAttachments(string attachNotify)
{
try
{
cmdBarMailItem.IsEnabled = false;
if (await Device.IsNetworkAvailable())
{
cts = new CancellationTokenSource();
// Ignore SSL Certificate which is untrusted,expired and has invalid hostname.
var filter = new HttpBaseProtocolFilter() { AllowUI = false };
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Expired);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.InvalidName);
// Start calling the soap service #userGetAttachmentByIndex
using (var client = new System.Net.Http.HttpClient(new WinRtHttpClientHandler(filter)))
{
//Prepare parameters which is to be post via soap envelope.
List<KeyValuePair<string, string>> parameter = new List<KeyValuePair<string, string>>();
parameter.Add(new KeyValuePair<string, string>("sessionId", GlobalInfo.SessionID));
parameter.Add(new KeyValuePair<string, string>("attachmentIndex", attachNotify.Split('|')[1].ToString()));
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
client.DefaultRequestHeaders.Add("SOAPAction", "userGetAttachmentByIndex");
var postContent = new StringContent(StringHelper.ConstructSoapRequest(parameter, "userGetAttachmentByIndex"), Encoding.UTF8, "text/xml");
// Getting response from soap service
var response = await client.PostAsync(new Uri(AppEnv.ServiceEndPoint), postContent, cts.Token);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string soapResponse = await response.Content.ReadAsStringAsync();
var soap = XDocument.Parse(soapResponse);
XNamespace ns = "http://service.webservice.cryoserver.ci";
var base64BinaryStr = soap.Descendants(ns + "userGetAttachmentByIndexResponse").First().Descendants(ns + "return").First().Descendants(ns + "attachmentType").First().Descendants(ns + "binaryData").First().Descendants(ns + "base64Binary").First().Value;
await saveStringToLocalFile(base64BinaryStr);
var file = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync("myTest.pdf");
bool x = await Windows.System.Launcher.LaunchFileAsync(file);
return x;
}
}
}
cmdBarMailItem.IsEnabled = true;
}
catch (TaskCanceledException)
{
PopupRetrieve.IsOpen = false;
ProgressBar.IsVisible = false;
cmdBarMailItem.IsEnabled = true;
}
catch(Exception ex)
{
cmdBarMailItem.IsEnabled = true;
ProgressBar.IsVisible = false;
MessageBox.Show(AlertType.Connectivity);
}
return null;
}
async Task saveStringToLocalFile(string content)
{
try
{
// saves the string 'content' to a file 'filename' in the app's local storage folder
// byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(content.ToCharArray());
byte[] byteArray = Convert.FromBase64String(content);
// create a file with the given filename in the local folder; replace any existing file with the same name
StorageFile file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("myTest.pdf", CreationCollisionOption.ReplaceExisting);
// write the char array created from the content string into the file
using (var stream = await file.OpenStreamForWriteAsync())
{
stream.Write(byteArray, 0, byteArray.Length);
stream.Flush();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I got the exception on executing the line
string soapResponse = await response.Content.ReadAsStringAsync();
Anybody have an idea why the exception occurs ? What could be possible solution to fix it.
Any help would be appriciable. :)

Upload a post with description and title using facebook c# sdk

I used the following code. Picture is posted successfully with a name but its not able to post message/description with it. Please tell me where i am wrong. Also its not giving any exception.
private void SharePhoto(string _accessToken, string p)
{
var fb = new FacebookClient(_accessToken);
fb.PostCompleted += (o, args) =>
{
if (args.Error != null)
{
if (args.Error.Message.StartsWith("(OAuthException - #190)"))
{
Dispatcher.BeginInvoke(() =>
{ MessageBox.Show("Message Expired"); });
}
else
{
Dispatcher.BeginInvoke(() =>
{ MessageBox.Show(args.Error.Message, "Error", MessageBoxButton.OK); });
}
return;
}
else
{
Dispatcher.BeginInvoke(() =>
{ MessageBox.Show("Image Posted"); });
}
};
var fbupload = new FacebookMediaObject
{
FileName = "facebook.jpg",
ContentType = "image/jpeg"
};
StreamResourceInfo sri =Application.GetResourceStream(new Uri("facebook.jpg",UriKind.Relative));
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(sri.Stream);
var loadedImage = new WriteableBitmap(bitmap);
using (MemoryStream ms = new MemoryStream())
{
loadedImage.SaveJpeg(ms, loadedImage.PixelWidth, loadedImage.PixelHeight, 0, 95);
ms.Seek(0, 0);
byte[] data = new byte[ms.Length];
ms.Read(data, 0, data.Length);
ms.Close();
fbupload.SetValue(data);
}
var parameters = new Dictionary<string, object>();
parameters["message"] = txtMessage.Text;
parameters["description"] = "first ever one";
parameters["name"] = "My FB Pic";
parameters["picture"]=fbupload;
parameters["link"] = new Uri(#"http://www.anyxyz.com", UriKind.Absolute);
fb.PostAsync(#"me/photos", parameters);
}
I used extended permissions as:
private const string extendedPermissions = "user_about_me,read_stream,publish_stream";
Any Help would be greatly appreciated.