form data going as null to HttpContext.Current.Request [duplicate] - javascript

This question already has an answer here:
How to POST binary files with AngularJS (with upload DEMO)
(1 answer)
Closed 4 years ago.
I have a file upload module.its working well with postman with no content type.but in code always file count is getting as 0 in backend api.if anyone knows what i am doing wrong,please help me. thanks
here is my back end api`
public async Task<HttpResponseMessage> PostUserImage()
{
Dictionary<string, object> dict = new Dictionary<string, object>();
try
{
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
var postedFile = httpRequest.Files[file];
if (postedFile != null && postedFile.ContentLength > 0)
{
int MaxContentLength = 1024 * 1024 * 1; //Size = 1 MB
IList<string> AllowedFileExtensions = new List<string> { ".jpg", ".gif", ".png" };
var ext = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf('.'));
var extension = ext.ToLower();
if (!AllowedFileExtensions.Contains(extension))
{
var message = string.Format("Please Upload image of type .jpg,.gif,.png.");
dict.Add("error", message);
return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
}
else if (postedFile.ContentLength > MaxContentLength)
{
var message = string.Format("Please Upload a file upto 1 mb.");
dict.Add("error", message);
return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
}
else
{
var filePath = HttpContext.Current.Server.MapPath("~/Image/" + postedFile.FileName + extension);
postedFile.SaveAs(filePath);
}
}
var message1 = string.Format("Image Updated Successfully.");
return Request.CreateErrorResponse(HttpStatusCode.Created, message1); ;
}
var res = string.Format("Please Upload a image.");
dict.Add("error", res);
return Request.CreateResponse(HttpStatusCode.NotFound, dict);
}
catch (Exception ex)
{
var res = string.Format("some Message");
dict.Add("error", res);
return Request.CreateResponse(HttpStatusCode.NotFound, dict);
}
}`
this is what i am getting after posting through postman
and this is what i am getting in my developer console.
my angular service foe uploading`
uploadimage:function(file,operation){
var deferred = $q.defer();
var httpReq = {
method: operation,
url: '/API/Customers/PostUserImage',
data:file,
transformRequest: angular.identity,
headers: {
'content-type': 'multipart/form-data'
},
onSuccess: function (response, status) {
deferred.resolve(response);
},
onError: function (response) {
deferred.reject(response);
}
};
httpService.call(httpReq);
return deferred.promise;
}`
this the controller code for appending to form data`
function readURL(input) {
debugger;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#imagePreview').css('background-image', 'url('+e.target.result +')');
$('#imagePreview').hide();
$('#imagePreview').fadeIn(650);
}
reader.readAsDataURL(input.files[0]);
var filesformdata = new FormData();
angular.forEach(input.files, function (value, key) {
filesformdata.append(key, value);
});
for (var pair of filesformdata.entries()) {
console.log(pair[0] + ', ' + pair[1]);
console.log(pair[1]);
}
profileService.uploadimage(filesformdata,"POST").then(function(response){
toastr.success("profilepicture changed");
});
}
}
and here is http request `

use API like
public async Task<HttpResponseMessage> MethodName()
{
if (HttpContext.Current.Request.ContentType == "application/x-www-form-urlencoded")
{
var ParameterName = int.Parse(HttpContext.Current.Request.Form.GetValues("ParameterName")[0].ToString());
}
else
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
}
var response = Request.CreateResponse(objreturn);
return response;
}

When sending non-alphanumeric file or big payload, you should be using form enctype attribute value of "multipart/form-data".
<form enctype="multipart/form-data" ...
Example: HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME
public async Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}

Related

Trying to download zip file from server using AngularJs and c# webapi

I know that posts with similar titles exist, but it doesn't work for me its how I try to achieve that:
WebApi
public async Task<HttpResponseMessage> ExportAnalyticsData([FromODataUri] int siteId, [FromODataUri] string start, [FromODataUri] string end) {
DateTime startDate = Date.Parse(start);
DateTime endDate = Date.Parse(end);
using (ZipFile zip = new ZipFile()) {
using (var DailyLogLanguagesCsv = new CsvWriter(new StreamWriter("src"))) {
var dailyLogLanguages = await _dbContext.AggregateDailyLogSiteObjectsByDates(siteId, startDate, endDate).ToListAsync();
DailyLogLanguagesCsv.WriteRecords(dailyLogLanguages);
zip.AddFile("src");
}
using (var DailyLogSiteObjectsCsv = new CsvWriter(new StreamWriter("src"))) {
var dailyLogSiteObjects = await _dbContext.AggregateDailyLogSiteObjectsByDates(siteId, startDate, endDate).ToListAsync();
DailyLogSiteObjectsCsv.WriteRecords(dailyLogSiteObjects);
zip.AddFile("src");
}
zip.Save("src");
HttpResponseMessage result = null;
var localFilePath = HttpContext.Current.Server.MapPath("src");
if (!File.Exists(localFilePath)) {
result = Request.CreateResponse(HttpStatusCode.Gone);
} else {
// Serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "Analytics";
}
return result;
}
}
AngularJs
$scope.exportData = function () {
apiService.dailyLog.exportAnalyticsData($scope.siteId, $scope.startDate, $scope.finishDate).then(function (response) {
debugger;
var blob = new Blob([response.data], { type: "application/zip" });
saveAs(blob, "analytics.zip");
})
};
function saveAs(blob, fileName) {
var url = window.URL.createObjectURL(blob);
var doc = document.createElement("a");
doc.href = url;
doc.download = fileName;
doc.click();
window.URL.revokeObjectURL(url);
}
And when I download a file I get information that the file is damaged. It only happens when I return zip file. It works well for csv.
After #wannadream suggestions and edited my code
else
{
// Serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "Analytics";
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
}
I have such problem when i try to open downloaded zip.
Try accessing the WebAPI controller action through a normal browser, and see if the ZIP it downloads can open. If it can't, then your problem is in your WebAPI.
zip.AddFile("src"); and then zip.Save("src"); ? It does not make sense.
You are zipping 'src' with target name 'src'. Try another name for zip file.
zip.Save("target")
var localFilePath = HttpContext.Current.Server.MapPath("target");
Try set this:
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
I resolve it by set a type responseType
{ type: "application/octet-stream", responseType: 'arraybuffer' }
and the same thing in my apiService
$http.get(serviceBase + path), {responseType:'arraybuffer'});
This can be done using DotNetZip and set the response type as arraybuffer, check below code for complete understanding.
1.WebApi Controller
[HttpPost]
[Route("GetContactFileLink")]
public HttpResponseMessage GetContactFileLink([FromBody]JObject obj)
{
string exportURL = "d:\\xxxx.text";//replace with your filepath
var fileName = obj["filename"].ToObject<string>();
exportURL = exportURL+fileName;
var resullt = CreateZipFile(exportURL);
return resullt;
}
private HttpResponseMessage CreateZipFile(string directoryPath)
{
try
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
using (ZipFile zip = new ZipFile())
{
zip.AlternateEncodingUsage = ZipOption.AsNecessary;
zip.AddFile(directoryPath, "");
//Set the Name of Zip File.
string zipName = String.Format("Zip_{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
using (MemoryStream memoryStream = new MemoryStream())
{
//Save the Zip File to MemoryStream.
zip.Save(memoryStream);
//Set the Response Content.
response.Content = new ByteArrayContent(memoryStream.ToArray());
//Set the Response Content Length.
response.Content.Headers.ContentLength = memoryStream.ToArray().LongLength;
//Set the Content Disposition Header Value and FileName.
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
//Set the File Content Type.
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
return response;
}
}
}
catch(Exception ex)
{
throw new ApplicationException("Invald file path or file not exsist");
}
}
2.Angular component
function getcontactFileLink(token, params) {
return $http.post('api/event/GetContactFileLink', params, { headers: { 'Authorization': 'Bearer ' + token, 'CultureCode': cc }, 'responseType': 'arraybuffer' }).then(response);
function response(response) {
return response;
}
}
function showcontactfile(item) {
usSpinnerService.spin('spinner-1');
var params = {};
params.filename = item.filename;
EventListingProcess.getcontactFileLink(accessToken, params).then(function (result) {
var blob = new Blob([result.data], { type: "application/zip" });
var fileName = item.filename+".zip";
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display:none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}).catch(function (error) {
vm.message = frameworkFactory.decodeURI(error.statusText);
//frameworkFactory.translate(vm, 'message', error.statusText);
}).finally(function () {
usSpinnerService.stop('spinner-1');
});
}

A console application to get a web page resource, using c# (javascript may cause this)

Aim: To download a website source with using a console application. You can find the used class in the program below.
Question: I use the code below to download a data (source) of a web page. Imagine you use chrome; If you enter first this query string, the web page itself redirects you a view HTML page and you see the data.
Entering this URL, to show the results it redirects itself to second page below. I make it by using javascript.
www.xyz.com/aaa.html?search=aaa&id=1
it redirects here: www.xyz.com/ViewResult.html
In an explorer, It works fine . I see 4 HTML tables inside the page when I use google chrome view source option. Bu in my application I see only two tables of the 4 . The two tables inside the web page is missing.(the missing two tables are the second and third.)
How can I overcome to this problem? I want to get the source of the page as I see in chrome.
Bonus informations: There is no iframe.
The particular Code :
string url = "www.xyz.com/aaa.html?search=aaa&id=1";
WebPage pG = ss.RequestPage(url, "", "GET");
pG = ss.RequestPage("www.xyz.com/ViewResult.html");
string source= pG.Html;
public WebPage RequestPage(Uri url, string content, string method, string contentType)
{
string htmlResult;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
HttpWebResponse response = null;
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] contentData = encoding.GetBytes(content);
request.Proxy = Proxy;
request.Timeout = 60000;
request.Method = method;
request.AllowAutoRedirect = false; // false
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Referer = LastUrl;
request.KeepAlive = true; //false,
request.UserAgent = UserAgent;
request.Headers.Add("Accept-Language", "en-us,en;q=0.5");
//request.Headers.Add("UA-CPU", "x86");
request.Headers.Add("Cache-Control", "no-cache");
request.Headers.Add("Accept-Encoding", "gzip,deflate");
String cookieString = "";
foreach (KeyValuePair<String, String> cookiePair in Cookies)
cookieString += cookiePair.Key + "=" + cookiePair.Value + ";";
if (cookieString.Length > 2)
{
String cookie = cookieString.Substring(0, cookieString.Length - 1);
request.Headers.Add("Cookie", cookie);
}
if (method == "POST")
{
request.ContentLength = contentData.Length;
request.ContentType = contentType;
Stream contentWriter = request.GetRequestStream();
contentWriter.Write(contentData, 0, contentData.Length);
contentWriter.Close();
}
int attempts = 0;
while (true)
{
try
{
response = (HttpWebResponse)request.GetResponse();
if (response == null)
throw new WebException();
break;
}
catch (WebException)
{
if (response != null)
response.Close();
if (attempts == PageReattempts)
{
throw;
}
else { }
// Wait three seconds before trying again
Thread.Sleep(3000);
}
attempts += 1;
}
// Tokenize cookies
if (response.Headers["Set-Cookie"] != null)
{
String headers = response.Headers["Set-Cookie"].Replace("path=/,", ";").Replace("HttpOnly,", "");
foreach (String cookie in headers.Split(';'))
{
if (cookie.Contains("="))
{
String[] splitCookie = cookie.Split('=');
String cookieKey = splitCookie[0].Trim();
String cookieValue = splitCookie[1].Trim();
if (Cookies.ContainsKey(cookieKey))
Cookies[cookieKey] = cookieValue;
else
Cookies.Add(cookieKey, cookieValue);
}
else
{
if (Cookies.ContainsKey(cookie))
Cookies[cookie] = "";
else
Cookies.Add(cookie, "");
}
}
}
htmlResult = ReadResponseStream(response);
response.Close();
if (response.Headers["Location"] != null)
{
response.Close();
Thread.Sleep(1500);
String newLocation = response.Headers["Location"];
WebPage result = RequestPage(newLocation);
return new WebPage(result.Html, new WebPage(htmlResult));
}
LastUrl = url.ToString();
return new WebPage(htmlResult);
}
1-WebBrowser :
public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser
{
public ExtendedWebBrowser()
{
// Ensure that ScriptErrorsSuppressed is set to false.
this.ScriptErrorsSuppressed = true;
this.ProgressChanged += ExtendedWebBrowser_ProgressChanged;
}
private void ExtendedWebBrowser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
{
// InjectAlertBlocker();
string alertBlocker = #"window.alert = function () { };
window.print = function () { };
window.open = function () { };
window.onunload = function () { };
window.onbeforeunload = function () { };";
var webBrowser = sender as WebBrowser;
webBrowser?.Document?.InvokeScript("execScript", new Object[] { alertBlocker, "JavaScript" });
this.Document?.InvokeScript("execScript", new Object[] { alertBlocker, "JavaScript" });
}
public void NavigationWaitToComplete(string url)
{
bool complete = false;
NavigationAsync(url).ContinueWith((t) => complete = true);
while (!complete)
{
System.Windows.Forms.Application.DoEvents();
}
}
public void NavigationWaitToComplete(string url, string targetFrameName, byte[] postData, string additionalHeaders)
{
bool complete = false;
NavigationAsync(url, targetFrameName, postData, additionalHeaders).ContinueWith((t) => complete = true);
while (!complete)
{
System.Windows.Forms.Application.DoEvents();
}
}
public async Task NavigationAsync(string url, string targetFrameName, byte[] postData, string additionalHeaders)
{
TaskCompletionSource<bool> tcsNavigation = new TaskCompletionSource<bool>(); ;
TaskCompletionSource<bool> tcsDocument = new TaskCompletionSource<bool>(); ;
Navigated += (s, e) =>
{
if (tcsNavigation.Task.IsCompleted)
return;
tcsNavigation.SetResult(true);
};
DocumentCompleted += (s, e) =>
{
if (ReadyState != WebBrowserReadyState.Complete)
return;
if (tcsDocument.Task.IsCompleted)
return;
tcsDocument.SetResult(true);
};
Navigate(url, targetFrameName, postData, additionalHeaders);
await tcsNavigation.Task;
// navigation completed, but the document may still be loading
await tcsDocument.Task;
// the document has been fully loaded, you can access DOM here
}
public async Task NavigationAsync(string url)
{
TaskCompletionSource<bool> tcsNavigation = new TaskCompletionSource<bool>(); ;
TaskCompletionSource<bool> tcsDocument = new TaskCompletionSource<bool>(); ;
Navigated += (s, e) =>
{
if (tcsNavigation.Task.IsCompleted)
return;
tcsNavigation.SetResult(true);
};
DocumentCompleted += (s, e) =>
{
if (ReadyState != WebBrowserReadyState.Complete)
return;
if (tcsDocument.Task.IsCompleted)
return;
tcsDocument.SetResult(true);
};
Navigate(url);
await tcsNavigation.Task;
// navigation completed, but the document may still be loading
await tcsDocument.Task;
// the document has been fully loaded, you can access DOM here
}
}
Calling:
var browser = new ExtendedWebBrowser();
browser.NavigationWaitToComplete("www.xyz.com/aaa.html?search=aaa&id=1");
var html = browser.Document.Body.OuterHtml();
2-CefSharp.OffScreen
private async Task<string> RequestPageAsync(string url, string cachePath, double zoomLevel)
{
var tcs = new TaskCompletionSource<string>();
var browserSettings = new BrowserSettings();
//Reduce rendering speed to one frame per second so it's easier to take screen shots
browserSettings.WindowlessFrameRate = 1;
var requestContextSettings = new RequestContextSettings { CachePath = cachePath };
// RequestContext can be shared between browser instances and allows for custom settings
// e.g. CachePath
using (var requestContext = new RequestContext(requestContextSettings))
using (var browser = new ChromiumWebBrowser(url, browserSettings, requestContext))
{
if (zoomLevel > 1)
{
browser.FrameLoadStart += (s, argsi) =>
{
var b = (ChromiumWebBrowser)s;
if (argsi.Frame.IsMain)
{
b.SetZoomLevel(zoomLevel);
}
};
}
browser.FrameLoadEnd += (s, argsi) =>
{
var b = (ChromiumWebBrowser)s;
if (argsi.Frame.IsMain)
{
b.GetSourceAsync().ContinueWith(taskHtml =>
{
tcs.TrySetResult(taskHtml.Result);
});
}
};
}
return tcs.Task.Result;
}
Calling :
RequestPageAsync("www.xyz.com/aaa.html?search=aaa&id=1", "cachePath1", 1.0);

XMPP File Transfer via JavaScript Strophe.js in Openfire

I am trying to get Strophe.js based XMPP file transfer to work. I can get logged in to work on my openfire server. I can send messages and receive messages fine but I am having trouble with file transfer.
HTML:
<form name='file_form' class="panel-body">
<input type="file" id="file" name="file[]" />
<input type='button' id='btnSendFile' value='sendFile' />
<output id="list"></output>
</form>
Javascript file:
// file
var sid = null;
var chunksize;
var data;
var file = null;
var aFileParts, mimeFile, fileName;
function sendFileClick() {
file =$("#file")[0].files[0];
sendFile(file);
readAll(file, function(data) {
log("handleFileSelect:");
log(" >data="+data);
log(" >data.len="+data.length);
});
}
function sendFile(file) {
var to = $('#to').get(0).value;
var filename = file.name;
var filesize = file.size;
var mime = file.type;
chunksize = filesize;
sid = connection._proto.sid;
log('sendFile: to=' + to);
// send a stream initiation
connection.si_filetransfer.send(to, sid, filename, filesize, mime, function(err) {
fileTransferHandler(file, err);
});
}
function fileTransferHandler(file, err) {
log("fileTransferHandler: err=" + err);
if (err) {
return console.log(err);
}
var to = $('#to').get(0).value;
chunksize = file.size;
chunksize = 20 * 1024;
// successfully initiated the transfer, now open the band
connection.ibb.open(to, sid, chunksize, function(err) {
log("ibb.open: err=" + err);
if (err) {
return console.log(err);
}
readChunks(file, function(data, seq) {
sendData(to, seq, data);
});
});
}
function readAll(file, cb) {
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
cb(evt.target.result);
}
};
reader.readAsDataURL(file);
}
function readChunks(file, callback) {
var fileSize = file.size;
var chunkSize = 20 * 1024; // bytes
var offset = 0;
var block = null;
var seq = 0;
var foo = function(evt) {
if (evt.target.error === null) {
offset += chunkSize; //evt.target.result.length;
seq++;
callback(evt.target.result, seq); // callback for handling read chunk
} else {
console.log("Read error: " + evt.target.error);
return;
}
if (offset >= fileSize) {
console.log("Done reading file");
return;
}
block(offset, chunkSize, file);
}
block = function(_offset, length, _file) {
log("_block: length=" + length + ", _offset=" + _offset);
var r = new FileReader();
var blob = _file.slice(_offset, length + _offset);
r.onload = foo;
r.readAsDataURL(blob);
}
block(offset, chunkSize, file);
}
function sendData(to, seq, data) {
// stream is open, start sending chunks of data
connection.ibb.data(to, sid, seq, data, function(err) {
log("ibb.data: err=" + err);
if (err) {
return console.log(err);
}
// ... repeat calling data
// keep sending until you're ready you've reached the end of the file
connection.ibb.close(to, sid, function(err) {
log("ibb.close: err=" + err);
if (err) {
return console.log(err);
}
// done
});
});
}
$('#btnSendFile').bind('click', function() {
console.log('File clicked:');
sendFileClick();
});
Full code is based on:
Complete example of Strophe.js file transfer
http://plnkr.co/edit/fYpXo1mFRWPxrLlgr123 (source can be download here: has errors). I changed the sendFileClick function.
I am getting:
ibb.open: err=Error: feature-not-implemented? Why is this error I am getting?

upload image binary - using imageshack api

Moving a topic from google groups to here so it can help someone who is asking.
imageshack api: http://api.imageshack.us/
the final http reqeust is returning json:
{"success":true,"process_time":325,"result":{"max_filesize":5242880,"space_limit":52428800,"space_used":0,"space_left":52428800,"passed":0,"failed":0,"total":0,"images":[]}}
which is not good, as it didn't upload :(
it should return an image object. http://api.imageshack.us/#h.ws82a1l6pp9g
as this is what the upload image section on the imageshack api says
please help :(
my extension code
var blobUrl;
var makeBlob = function () {
bigcanvas.toBlob(function (blob) {
var reader = new window.FileReader();
reader.readAsBinaryString(blob);
reader.onloadend = function () {
blobBinaryString = reader.result;
blobUrl = blobBinaryString;
Cu.reportError(blobUrl);
uploadBlob();
}
});
};
var uploadedImageUrl;
var uploadBlob = function () {
HTTP('POST', 'https://api.imageshack.us/v1/images', {
contentType: 'application/x-www-form-urlencoded',
//'album=' + urlencode('Stock History') + '&
body: 'auth_token=' + urlencode(auth_token) + 'file#=' + blobUrl,
onSuccess: function (status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest SUCCESS - imageshack uploadBlob\n' + statusText + '\n' + responseText);
eval('var json = ' + responseText);
uploadedImageUrl = json.direct_link;
submitBamdex();
},
onFailure: function (status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest FAILLLLLLLL - imageshack uploadBlob\n' + statusText + '\n' + responseText);
}
});
};
makeBlob(); //callllll the func
What worked for me was reading about
the differences between URI's, files, blobs and Base64's in this article: https://yaz.in/p/blobs-files-and-data-uris/ .
fetching a new blob: https://masteringjs.io/tutorials/axios/form-data
and much more closed tabs along the way
so in my react component onChange handler I use new FileReader to read event.target.files[0], readAsDataURL(file), and set the Base64 encoded string to state.
I conditionally render an img src={base64stringfromState} to offer confirmation of correct image, then onSubmit, I convert this "Data URI" (the Base64 string), to a blob with one of these two codes I found somewhere (didn't end up using the first one but this is useful af and took forever to find):
const dataURItoBlob = (dataURI) => {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
And
const blob = await fetch(base64imageString).then(res => res.blob())
Instead of all that shit we can just do this fetch a new version of the image or whatever and blob it right there, in the middle of constructing our photo upload/request :
event.preventDefault()
const blob = await fetch(base64stringfromState).then(res => res.blob())
const formData = new FormData()
formData.append('file#', blob)
formData.append('api_key', 'XXXXX')
formData.append('auth_token', 'XXXXXXXXXX')
formData.append('album', 'youralbumname')
const res = await axios.post('https://api.imageshack.com/v2/images', formData, {headers{'Content-Type':'multipart/form-data'}})
then all we have to do to store the uploaded image is to append https:// to and record the returned direct link for storage alongside its id so you can delete it if you need to later. Per the code earlier they spit out at
res.data.result.images[0].direct_link
res.data.result.images[0].id
This was a bitch to solve so hopefully this helps someone else with uploading photos to imageshack api cuz it's potentially a great value considering the limits of the competitors.
this code uploads a drawing on a canvas to imageshack
Can copy paste but have to update some things:
update username
update password
uploads drawing from canvas with id "bigcanvas"
update your API key
...
//this code uploads a drawing on a canvas to imageshack
var auth_token;
var loginImageshack = function() {
HTTP('POST','https://api.imageshack.us/v1/user/login',{
contentType: 'application/x-www-form-urlencoded',
body: 'user=USERNAME_TO_IMAGESHACK_HERE&password=' + urlencode('PASSWORD_TO_USERNAME_FOR_IMAGESHACK_HERE'),
onSuccess: function(status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest SUCCESS - imageshack login\n' + statusText + '\n' + responseText);
eval('var json = ' + responseText);
auth_token = json.result.auth_token;
makeImageshackFile();
},
onFailure: function(status, responseXML, responseText, headers, statusText) {
Cu.reportError('XMLHttpRequest FAILLLLLLLL - imageshack login\n' + statusText + '\n' + responseText);
}
});
};
var uploadedImageUrl;
var makeImageshackFile = function() {
var fd = new window.FormData();
fd.append("api_key", 'A835WS6Bww584g3568efa2z9823uua5ceh0h6325'); //USE YOUR API KEY HERE
fd.append("auth_token", auth_token);
fd.append('album', 'Stock History');
fd.append('title', 'THE-title-you-want-showing-on-imageshack')
fd.append("file#", bigcanvas.mozGetAsFile("foo.png")); //bigcanvas is a canvas with the image drawn on it: var bigcanvas = document.querySelector('#bigcanvas');
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
switch (xhr.readyState) {
case 4:
if (xhr.status==0 || (xhr.status>=200 && xhr.status<300)) {
Cu.reportError('XHR SUCCESS - \n' + xhr.responseText);
eval('var json = ' + xhr.responseText);
//ensure it passed else redo it I didnt program in the redo thing yet
//succesful json == {"success":true,"process_time":1274,"result":{"max_filesize":5242880,"space_limit":52428800,"space_used":270802,"space_left":52157998,"passed":1,"failed":0,"total":1,"images":[{"id":1067955963,"server":703,"bucket":2397,"lp_hash":"jj9g5p","filename":"9g5.png","original_filename":"foo.png","direct_link":"imageshack.us\/a\/img703\/2397\/9g5.png","title":"082813 200AM PST","description":null,"tags":[""],"likes":0,"liked":false,"views":0,"comments_count":0,"comments_disabled":false,"filter":0,"filesize":1029,"creation_date":1377681549,"width":760,"height":1110,"public":true,"is_owner":true,"owner":{"username":"bamdex","avatar":{"server":0,"filename":null}},"next_images":[],"prev_images":[{"server":59,"filename":"06mm.png"},{"server":706,"filename":"a1fg.png"}],"related_images":[{"server":59,"filename":"06mm.png"},{"server":41,"filename":"xn9q.png"},{"server":22,"filename":"t20a.png"},{"server":547,"filename":"fipx.png"},{"server":10,"filename":"dg6b.png"},{"se
uploadedImageUrl = json.result.images[0].direct_link;
Cu.reportError('succesfully uploaded image');
} else {
Cu.reportError('XHR FAIL - \n' + xhr.responseText);
}
break;
default:
//blah
}
}
xhr.open("POST", "https://api.imageshack.us/v1/images");
xhr.send(fd);
}
loginImageshack();
important note for code above
should use JSON.parse instead of eval if you want to submit the addon to AMO
should also probably change from using window to Services.appShel.hiddenDOMWindow so like new window.FormData(); would become new Services.appShel.hiddenDOMWindow.FormData(); OR var formData = Components.classes["#mozilla.org/files/formdata;1"].createInstance(Components.interfaces.nsIDOMFormData); OR Cu.import('resource://gre/modules/FormData.jsm')
helper functions required for the code above:
const {classes: Cc, interfaces: Ci, utils: Cu, Components: components} = Components
Cu.import('resource://gre/modules/Services.jsm');
...
function urlencode(str) {
return escape(str).replace(/\+/g,'%2B').replace(/%20/g, '+').replace(/\*/g, '%2A').replace(/\//g, '%2F').replace(/#/g, '%40');
};
...
//http request
const XMLHttpRequest = Cc["#mozilla.org/xmlextras/xmlhttprequest;1"];
/**
* The following keys can be sent:
* onSuccess (required) a function called when the response is 2xx
* onFailure a function called when the response is not 2xx
* username The username for basic auth
* password The password for basic auth
* overrideMimeType The mime type to use for non-XML response mime types
* timeout A timeout value in milliseconds for the response
* onTimeout A function to call if the request times out.
* body A string containing the entity body of the request
* contentType The content type of the entity body of the request
* headers A hash of optional headers
*/
function HTTP(method,url,options)
{
var requester = new XMLHttpRequest();
var timeout = null;
if (!options.synchronizedRequest) {
requester.onreadystatechange = function() {
switch (requester.readyState) {
case 0:
if (options.onUnsent) {
options.onUnsent(requester);
}
break;
case 1:
if (options.onOpened) {
options.onOpened(requester);
}
break;
case 2:
if (options.onHeaders) {
options.onHeaders(requester);
}
break;
case 3:
if (options.onLoading) {
options.onLoading(requester);
}
break;
case 4:
if (timeout) {
clearTimeout(timeout);
}
if (requester.status==0 || (requester.status>=200 && requester.status<300)) {
options.onSuccess(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
} else {
if (options.onFailure) {
options.onFailure(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
}
}
break;
}
}
}
if (options.overrideMimeType) {
requester.overrideMimeType(options.overrideMimeType);
}
if (options.username) {
requester.open(method,url,!options.synchronizedRequest,options.username,options.password);
} else {
requester.open(method,url,!options.synchronizedRequest);
}
if (options.timeout && !options.synchronizedRequest) {
timeout = setTimeout(
function() {
var callback = options.onTimeout ? options.onTimeout : options.onFailure;
callback(0,"Operation timeout.");
},
options.timeout
);
}
if (options.headers) {
for (var name in options.headers) {
requester.setRequestHeader(name,options.headers[name]);
}
}
if (options.sendAsBinary) {
Cu.reportError('sending as binary');
requester.sendAsBinary(options.body);
} else if (options.body) {
requester.setRequestHeader("Content-Type",options.contentType);
requester.send(options.body);
} else {
requester.send(null);
}
if (options.synchronizedRequest) {
if (requester.status==0 || (requester.status>=200 && requester.status<300)) {
options.onSuccess(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
} else {
if (options.onFailure) {
options.onFailure(
requester.status,
requester.responseXML,
requester.responseText,
options.returnHeaders ? _HTTP_parseHeaders(requester.getAllResponseHeaders()) : null,
requester.statusText
);
}
}
return {
abort: function() {
}
};
} else {
return {
abort: function() {
clearTimeout(timeout);
requester.abort();
}
};
}
}
function _HTTP_parseHeaders(headerText)
{
var headers = {};
if (headerText) {
var eol = headerText.indexOf("\n");
while (eol>=0) {
var line = headerText.substring(0,eol);
headerText = headerText.substring(eol+1);
while (headerText.length>0 && !headerText.match(_HTTP_HEADER_NAME)) {
eol = headerText.indexOf("\n");
var nextLine = eol<0 ? headerText : headerText.substring(0,eol);
line = line+' '+nextLine;
headerText = eol<0 ? "" : headerText.substring(eol+1);
}
// Parse the name value pair
var colon = line.indexOf(':');
var name = line.substring(0,colon);
var value = line.substring(colon+1);
headers[name] = value;
eol = headerText.indexOf("\n");
}
if (headerText.length>0) {
var colon = headerText.indexOf(':');
var name = headerText.substring(0,colon);
var value = headerText.substring(colon+1);
headers[name] = value;
}
}
return headers;
}

WinRT - StreamSocket - Connection closing while reading data via LoadAsync

I'm trying to send HTTP requests via StreamSocket, but response is truncated with
"failedWinRTError: The object has been closed."
Here is my code:
var count, hostName, raw_request, raw_response, reader, socketProtection, startReader, streamSocket, writer;
streamSocket = new Windows.Networking.Sockets.StreamSocket();
hostName = new Windows.Networking.HostName("www.reddit.com", "80");
raw_response = "";
count = 0;
startReader = function() {
return reader.loadAsync(8 * 1000).done(function(bytesRead) {
raw_response += reader.readString(reader.unconsumedBufferLength);
if (raw_response.indexOf("</html>") > 0) {
return;
} else {
startReader();
}
}, function(error) {
raw_response += reader.readString(reader.unconsumedBufferLength);
window.raw_response = raw_response;
return;
});
};
streamSocket.connectAsync(hostName, "80", 0).done(function(response) {
var string;
reader = new Windows.Storage.Streams.DataReader(streamSocket.inputStream);
reader.inputStreamOptions = 1;
writer = new Windows.Storage.Streams.DataWriter(streamSocket.outputStream);
string = "Hello world";
writer.writeString(raw_request);
return writer.storeAsync().done(function() {
writer.flushAsync();
writer.detachStream();
return startReader();
});
});
I noticed that the beginning of the response is truncated as well.
This is what I get at the beginning of HTTP responses.
/1.1 200 OK
Also strangely... HTTPS requests work perfectly.
Any idea what I'm doing wrong? Thanks :)
Remove http:// from the host name and the second parameter is not needed:
var hostName = new Windows.Networking.HostName("www.reddit.com");
Use this object in ConnectAsync, just hostname and service name parameters are needed:
streamSocket.connectAsync(hostName, "80").done(function (response) {
// ....
}, function (error) {
console.log(error);
});
UPDATE: Ok, if the connection is being closed, probably the server closes it. Are you sending a well formed request? Here is an example:
var raw_request, raw_response, reader, writer;
var streamSocket = new Windows.Networking.Sockets.StreamSocket();
function doRequest() {
var hostName = new Windows.Networking.HostName("www.reddit.com");
streamSocket.connectAsync(hostName, "808").then(function () {
reader = new Windows.Storage.Streams.DataReader(streamSocket.inputStream);
reader.inputStreamOptions = Windows.Storage.Streams.InputStreamOptions.partial;
writer = new Windows.Storage.Streams.DataWriter(streamSocket.outputStream);
raw_request = "GET / HTTP/1.1\r\nHost: www.reddit.com/\r\nConnection: close\r\n\r\n";
writer.writeString(raw_request);
return writer.storeAsync();
}).then(function () {
raw_response = "";
return startReader();
}, function (error) {
console.log(error);
});
}
function startReader() {
return reader.loadAsync(99999999).then(function (bytesRead) {
raw_response += reader.readString(reader.unconsumedBufferLength);
if (bytesRead === 0) {
window.raw_response.value = raw_response;
return;
}
return startReader();
});
};

Categories

Resources