How to get image directly? - android-image

Follwing webpage includes light adult contents. Please do not click link if you don't want it.
go to : http://www.hqasians.com/tgp/bigasiantits/MaiNishida/at.htm
you can see several thumb images.
click one of them. you can see large image.
Check current page url. It will be like ~~~~~~~~~~~~~~~~/tgp/bigasiantits/MaiNishida/images/01.jpg
you can know how to access another image by changing last .jpg name of whole url
change 01.jpg to 02.jpg and enter.
But, you will encounter website's main page not 02.jpg.
Is this security way to block direct access by that site ?
Is there any work-around way to get image directly?
Following is my codes.
InputStream bmis;
bmis = new URL(params[0]).openStream();
final Drawable image =
new BitmapDrawable(BitmapFactory.decodeStream(new FlushedInputStream(bmis)));
if(image != null)
{
activity.setContentView(imageSwitcher);
imageSwitcher.setImageDrawable(image);
}

I'm only guessing here, but I think what this site does is to check the "Referer" field from the HTTP request header to check whether the request came from within the site, or from outside.
It isn't a secure way of blocking direct access. In fact, there's an workaround, but I don't think the site rules allow me to write it here, so, you'll have to figure out yourself.

It's because of the Referrer. You have to be referred by that main page to open the picture.
Sorry I'm not sure how to use Android, but C# code should look like this:
static void Main(string[] args)
{
for (int i = 1; i <= 15; i++)
{
HttpWebRequest request =
WebRequest.Create(
string.Format("http://www.hqasians.com/tgp/bigasiantits/MaiNishida/images/{0:00}.jpg", i)
) as HttpWebRequest;
request.Credentials = CredentialCache.DefaultCredentials;
request.Referer = "http://www.hqasians.com/tgp/bigasiantits/MaiNishida/at.htm";
request.Method = "POST";
WebResponse response = request.GetResponse();
string inputFile = string.Format("{0}.jpg", i);
Console.WriteLine(response.ResponseUri.AbsoluteUri);
using (Stream file = File.OpenWrite(inputFile))
{
CopyStream(response.GetResponseStream(), file);
}
}
}
/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
The CopyStream method is got from here: How do I save a stream to a file in C#?

Related

How do I write an image's MemoryStream to the page body?

I'm converting ASP.NET WebForms code to ASP.NET Core Razor pages which is new to me. I'm trying to retrieve an image MemoryStream from a business class (based on SixLabors awesome ImageSharp) and have the page render the JPEG -- no HTML, just the image. I intend to use this page elsewhere as an <img> src, like <img src="Render?imageID=42&mode=invert" />
In Render.cshtml.cs:
public class RenderModel : PageModel
{
public void OnGet()
{
//snip
Stream stream = new MemoryStream();
using (Image image1 = Image.Load(imagePath))
{
SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder encoder = new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder();
encoder.Quality = 75;
image1.Save(stream, encoder);
//image.Save("/temp/xxx.jpg", encoder); //test to see image. it works
}
Response.Clear();
//Response.Headers.ContentLength = stream.Length;
Response.ContentType = "image/jpeg";
Response.Body = stream;
}
}
...but this is not working, I get:
System.InvalidOperationException: Response Content-Length mismatch: too few bytes written (0 of 135408).
135408 is the stream.Length.
I'm probably not doing this correctly in the ASP.NET Core/Razor way. Can anyone set me straight as to how to do this? Thanks!
EDIT: commenting out the Headers.ContentLength fixes the error. But now I get a broken-image icon in the browser. Closer...
You need to write to the Response.Body isntead of replacing it.
stream.Seek(0, SeekOrigin.Begin);
await stream.CopyToAsync(Response.Body);
await Response.Body.FlushAsync();
I think Razor pages are intented to return html content.
However it seems to be possible to return different types of result in OnGet e.g. you could return a new FileContentReset (FileStreamResult seems to have issues with contentlength)
// read as bytes
public FileContentResult OnGet()
{
var image = System.IO.File.ReadAllBytes(#"c:\temp\myimage.jpeg");
return new FileContentResult(image.ToArray(), "image/jpeg");
}
// example if image comes from stream
public FileContentResult OnGet()
{
using var imageStr = System.IO.File.Open(#"c:\temp\myimage.jpeg", FileMode.Open);
using var memStr = new MemoryStream();
imageStr.CopyTo(memStr);
return new FileContentResult(memStr.ToArray(), "image/jpeg");
}
Even better maybe it to not use a Razor page and to add a MVC controller to return the result.

"Cannot access a disposedObject" exception in Xamarin when attempting to send a byte[] to server

The old version of this question got too long so by the end of numerous attemts to solve this issue I came up that all can be taken down to a simple question. Why does this produce a SystemObjectDisposed.
private async void PickPhotoButton_OnClicked(object sender, EventArgs e)
{
_globalStream = await DependencyService.Get<IPicturePicker>
().GetImageStreamAsync();
_globalArray = StreamToByteArray(_globalStream);
var gal = new GalleryResource()
{
Pic = _globalArray
};
MemoryObjects.CurrentGallery = gal;
var ctr = HelperMethods.GetInstance<GalleryController>();
await ctr.Post();
}
public byte[] StreamToByteArray(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
The stream arrives from the native side, I turn it into a byte array and pass it into my repository. Everyting work with a dummy byte array so something is wrong with the stream object that possibly gets closed or disposed at point.
The exception is thrown in the repository at this point:
var response = await _client.PostAsync(endPoint, _repService.ConvertObjectToStringContent(obj));
ConvertObjectToStringContent(obj) - not this part of it. From here it actually returns with a value and the byte array is seen inside the debug ie. the byte array stay with a valid lenght all way through.
The only event that does take place when we do finish picking the photo from the library is the following:
void OnImagePickerFinishedPickingMedia(object sender,
UIImagePickerMediaPickedEventArgs args)
{
UIImage image = args.EditedImage ?? args.OriginalImage;
if (image != null)
{
// Convert UIImage to .NET Stream object
NSData data = image.AsJPEG(1);
Stream stream = data.AsStream();
// Set the Stream as the completion of the Task
taskCompletionSource.SetResult(stream);
}
else
{
taskCompletionSource.SetResult(null);
}
imagePicker.DismissModalViewController(true);
}
However it doesn't seem to dispose the stream and even if it did we already got a byte array from it.
Tried even doing this inside Native code
var client = new HttpClient();
var c = new MultipartFormDataContent();
c.Add(new StreamContent(image.AsJPEG(1).AsStream()));
var response = await client.PostAsync(Settings.EndPoint + "api/gallery/", c);
Same error.
I think your problem lies somewhere in this line _byteArray = ToByteArray(_array);
ToByteArray(stream) seems to return you the byte array maybe via conversion from a stream, and this stream might still have a reference to the bytearray. And it might have become disposed.
If it's inside this method, please post it, I wanna knowww
I'm not quite experienced enough to exactly tell what it is about, but maybe my suggestions will be hitting the right spot!
Btw your code looks real clean, I like it!
So, although this issue did come up in the first place with the CrossMedia plugin https://github.com/jamesmontemagno/MediaPlugin it did the same error.
However the error only comes up if you for instance pick a photo like this:
var _mediaFile = await CrossMedia.Current.PickPhotoAsync();
So, when I did this:
var _mediaFile = await CrossMedia.Current.PickPhotoAsync(new
Plugin.Media.Abstractions.PickMediaOptions
{
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Small,
CompressionQuality = 90,
});
The error went away. No idea why.

Security Sandbox Violation for module accessing localhost rest service in dev environment

Our app has a main module with link button, and clicking each link button loads different modules in the main content area.
For only one module, we get a Security Sandbox Violation when we try to do a multipart post of image data.
I can't find anything significantly different about this module, other modules do multipart posts fine.
I have added thre SWF and various folders (such as containing folder, its parent, etc.) to flash player global settings, but no luck. We added a liberal cross domain file but still no luck.
BTW, we are using ModuleLoader, should we try ModuleManager?
Please help.
Security Sandbox Violation
Connection to
http://localhost:PORTNUMBERHIDDEN/services/rest/mycompany/222/assetservice/asset?action=saveasset&objecttype=serviceOffer&objectid=5960&User-Agent=flex3.0&randomNum=1328144876976
halted - not permitted from
file:///C:/Perforce/Main/Portal/main/bin-debug/serviceOffer-2.4.0.18-SNAPSHOT.swf
I got the answer from this web post:
Unexpected Flash Security Exception When Using URLLoader
Instead of setting the contentType like this:
request.contentType = "multipart/form-data;boundary=" + POSTUploadBuilder.boundary;
Set the contentType like this:
request.requestHeaders.push(new URLRequestHeader('Content-Type', 'multipart/form-data;
boundary=' + POSTUploadBuilder.boundary));
This is how I create the boundry in my POSTUploadBuilder class:
public class POSTUploadBuilder {
private static var _boundary:String = "";
private static var _mainBoundary:String = "";
public static function get boundary():String {
if(_boundary.length == 0) {
var i:uint = 0;
var len:uint = 0x20;
for(; i < len; ++i) {
_boundary += String.fromCharCode(uint(97 + Math.random() * 25));
}
}
return _boundary;
}

how do I handle and deflate a GZipped form post in asp.net MVC?

I have an iPad app that submits orders to an ASP.NET MVC web site via form post. It is posting JSON which can be fairly large for a mobile device to send (200~300K) under certain conditions. I can GZip the form post but then my asp.net mvc chokes on the gzipped content.
How can I handle a GZipped form post in asp.net mvc?
UPDATE:
Darin's answer puts me on the right track but I still have no idea how to do what he suggests, so here is where I am at:
Have this code to decompress a string:
http://dotnet-snippets.com/dns/compress-and-decompress-strings-SID612.aspx
And I get the string like so:
StreamReader reader = new StreamReader(Request.InputStream);
string encodedString = reader.ReadToEnd();
but this gives me the error:
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters.
EDIT - COMPLETED CODE
I am using asp.net MVC and this is working great for me. I also had to deal with some other encoding that happens when my gzipping occurs:
[Authorize]
[HttpPost]
[ValidateInput(false)]
public ActionResult SubmitOrder()
{
GZipStream zipStream = new GZipStream(Request.InputStream, CompressionMode.Decompress);
byte[] streamBytes = ReadAllBytes(zipStream);
var result = Convert.ToBase64String(streamBytes);
string sample = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(result));
string escaped = Uri.UnescapeDataString(sample);
// escaped now has my form values as a string like so: var1=value1&var2=value2&ect...
//more boring code
}
public static byte[] ReadAllBytes(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
You can do this without a custom model binder. Write an Action that accepts HttpPostedFileBase, i.e, treat this as a file upload.
[HttpPost]
public ActionResult UploadCompressedJSON(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
GZipStream zipStream = new GZipStream(file.InputStream, CompressionMode.Decompress);
byte[] streamBytes = ReadAllBytes(zipStream);
var result = Convert.ToBase64String(streamBytes);
}
return RedirectToAction("Index");
}
You are going to need to change your client side code to send a file upload request but that should be fairly easy. For example you can look at this code.
How can I handle a GZipped form post in asp.net mvc?
You could write a custom model binder that will directly read the Request.InputStream, unzip it and then parse the contents and instantiate some view model you want to bind to.
Use the System.IO.Compression.GZipStream class.
Codeproject example

How do I make a simple post to Twitter via ASP.NET (VB, preferably)?

I don't want to do anything fancy on Twitter except post to it via my site once a day. I have searched around a bit and there are all sorts of super-complex ways to do every little thing that Twitter does, but there seems to be little documentation on how to do the simplest thing, which is make a post!
Does anyone know how to do this? Or can you at least point me in the right direction? I don't need full wrappers or anything (http://apiwiki.twitter.com/Libraries#C/NET), just one simple function that will post to Twitter.
Thanks!
This is the easiest implementation ever. Up and running in under 2 minutes: Twitterizer
Its fairly simple; you just need to post an xml file to a web page using webrequest.create. This example is close (assumes you have the xml for the message in another place and just pass it into twitterxml variable as a string. The url might not be the right one; found it on this [page][1] which defines the interface
WebRequest req = null;
WebResponse rsp = null;
try
{
string twitterXML = "xml as string";
string uri = "http://twitter.com/statuses/update.format";
req = WebRequest.Create(uri);
//req.Proxy = WebProxy.GetDefaultProxy(); // Enable if using proxy
req.Method = "POST"; // Post method
req.ContentType = "text/xml"; // content type
// Wrap the request stream with a text-based writer
StreamWriter writer = new StreamWriter(req.GetRequestStream());
// Write the XML text into the stream
writer.WriteLine(twitterXML);
writer.Close();
// Send the data to the webserver
rsp = req.GetResponse();
}
[1]: http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses update
There are a couple different ways of doing this, they vary depending on the tools you want to use and have access to. Option 1 will work right out of the box, but the coding can be complicated. Option 3 you will have to download tools for, but once there installed and loaded you should be able to consume the twitter api very quickly.
Use WebRequest.Create to create/send messages to remote endpoints
Use WCF, create a mirror endpoint and access the twitter api using client only endpoint.
Use the WCF REST Starter Kit Preview 2, which has a new class called the HttpClient. I would have to recommend this technique if you can. Here is a great video Consuming a REST Twitter Feed in under 3 minutes.
Here is a sample of using the WCF REST Starter Kit's HttpClient:
public void CreateFriendship(string friend)
{
using (var client = new HttpClient())
{
var url = string.Format("http://www.twitter.com/friendships/create/{0}.xml?follow=true", friend);
client.Post(url)
.CheckForTwitterError()
.EnsureStatusIs(HttpStatusCode.OK);
}
}
Add a comment if you'd like more info about a particular method.
Update:
For Option #1 see this question: Remote HTTP Post with C#
There are a few ways of doing this, you can check out http://restfor.me/twitter and it will give you the code from RESTful documentation.
Essentially making any authenticated call you can follow this logic:
///
/// Executes an HTTP POST command and retrives the information.
/// This function will automatically include a "source" parameter if the "Source" property is set.
///
/// The URL to perform the POST operation
/// The username to use with the request
/// The password to use with the request
/// The data to post
/// The response of the request, or null if we got 404 or nothing.
protected string ExecutePostCommand(string url, string userName, string password, string data) {
WebRequest request = WebRequest.Create(url);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password)) {
request.Credentials = new NetworkCredential(userName, password);
byte[] bytes = Encoding.UTF8.GetBytes(data);
request.ContentLength = bytes.Length;
using (Stream requestStream = request.GetRequestStream()) {
requestStream.Write(bytes, 0, bytes.Length);
using (WebResponse response = request.GetResponse()) {
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
return reader.ReadToEnd();
}
}
}
}
return null;
}

Resources