Sending Pictures to a Web Server

Webserver sending pictures over HTTP

You encode everything as a string.

For the HTTP header, this is fine, because all browsers expect the header to readable this way and it must be encoded using ASCII as you do now.

If you're sending text, it is also fine, because most browsers default to ASCII mode when you don't specify what the content type is.

But for images and other data, following must happen in your response.

Set the Content Type header specifying the type of the content you're sending.
examples would be

Content-Type: image/gif

or

Content-Type: image/png

Now the browser (or whatever that is receiving the content) knows what to expect. Except, you encoded your image in ASCII encoding.

ASCII is only for encoding simple test to bytes. (I say simple, because ASCII only supports very little set of characters. It doesn't support things like multiple languages .etc. which Unicode, UTF and some other encodings does.)

This causes ASCII to read your image, as text, and strip out or corrupt the letters it doesn't understand. (Which is most of your image data.)

What you want to do is, to send the rest of the response (image, after the header) in the format you specified in the Content-Type header. Simply send the result from ms.ToArray call.

Ideally, you will make sure the image is in the correct format you specified, and won't depend on the file extension, but in reality, lot of servers lie about the content type and specify image/* and let the browser figure it out.

Here's a good example on how to build a web server in C#.

Hope this helps.


On a side note, something your implementation is bad at, is memory consumption. You're loading the entire image to memory using a memory stream, then copying it to an array. That's 2 copies of the image in memory per request. I'm not sure how much scalability you want. But if you get 10 requests at the same time for a high resolution image (say 5 MB, for a typical photo taken by a 8MP camera ?), now your server suddenly loads 100 MB of data into memory.

This can become a larger problem if you're accepting files from user and loading them to memory before writing to a file. If a user decides to upload a file of 1 GB, it will bring down your server. (I've seen this in action in some sites written with ASP.NET, and it is very bad. Fault is partly ASP.NET's optimizations.)

What you can do is to open a file stream, and copy bytes to the response without loading the entire image. The above link shows the code for this.

c# Web Server - How to send images

HTTP request and response header have two line breaks(\n) to divide Header part and content part.

for example:

(Request that requesting an image(image.gif) from server)

GET /image.gif HTTP/1.1
User-Agent: WebBrowser
Accept-Encoding: deflate,gzip
Connection: keep-alive
... and more headers if present ...

(Response for image request)

HTTP/1.1 200 OK
Content-Length: <Length_Of_Content>
Content-Type: image/gif
... and more headers if present ...

<Data_Of_Image>





As you can see, there's two line breaks(\n) between response header and contents.

So, you have to read files as byte array(byte[]). In this situation, you can easily read files using System.IO.File.ReadAllBytes(string).

Now, one more left. I told you read files as byte array, but there's no way to join string and byte[]. So you have to encode string to byte[] and join header bytes and content bytes.
+ We can't send byte array via StreamWriter so, we'll use NetworkStream.

Here's explanation:

NetworkStream ns = client.GetStream();

...

string[] tokens = request.Split(' ');
string page = tokens[1];
if (page == "/")
{
page = "/default.htm";
}
//StreamReader file = new StreamReader("../../web" + page);
byte[] file = null;

try { file = File.ReadAllBytes(@"../../web" + page); }

// In this 'catch' block, you can't read requested file.
catch {
// do something (like printing error message)
}

// We are not going to use StreamWriter, we'll use StringBuilder
StringBuilder sbHeader = new StringBuilder();

// STATUS CODE
sbHeader.AppendLine("HTTP/1.1 200 OK");

// CONTENT-LENGTH
sbHeader.AppendLine("Content-Length: " + file.Length);

// Append one more line breaks to seperate header and content.
sbHeader.AppendLine();

// List for join two byte arrays.
List<byte> response = new List<byte>();

// First, add header.
response.AddRange(Encoding.ASCII.GetBytes(sbHeader.ToString()));

// Last, add content.
response.AddRange(file);

// Make byte array from List<byte>
byte[] responseByte = response.ToArray();

// Send entire response via NetworkStream
ns.Write(responseByte, 0, responseByte.Length);

This is it. I hope you can understand my bad english :O.
Hope this help to you!

how to post an image to the web server

Find here serverside (PHP) coding for image Upload with random name. also it will give the image link as response.

//Create a folder named images in your server where you want to upload the image.
// And Create a PHP file and use below code .

<?php
$uploaddir = 'images/';
$ran = rand () ;

$file = basename($_FILES['userfile']['name']);
$uploadfile = $uploaddir .$ran.$file;

if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "www.host.com/.../images/{$uploadfile}";
}
?>

And Here is iOS code

- (IBAction)uploadClicked:(id)sender
{
/*
turning the image into a NSData object
getting the image back out of the UIImageView
setting the quality to 90
*/
NSData *imageData = UIImageJPEGRepresentation(imageView.image, 90);
// setting up the URL to post to
NSString *urlString = @"your URL link";

// setting up the request object now
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];

/*
add some header info now
we always need a boundary when we post a file
also we need to set the content type

You might want to generate a random boundary.. this is just the same
as my output from wireshark on a valid html post
*/
NSString *boundary = [NSString stringWithString:@"---------------------------14737809831466499882746641449"];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];

/*
now lets create the body of the post
*/
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"rn--%@rn",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name="userfile"; filename="ipodfile.jpg"rn"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Type: application/octet-streamrnrn"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imageData]];
[body appendData:[[NSString stringWithFormat:@"rn--%@--rn",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[request setHTTPBody:body];

// now lets make the connection to the web
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];

NSLog(returnString);

}

Android app sends pictures to web server and pictures rotate

There is a property of the image, "exif tag". Which tells about the orientation of the image. You can check the value of this tag before sending the image to server.

you can use below method to get the unrotated image

public final static Bitmap getUnRotatedImage(String imahePath, Bitmap rotattedBitmap)
{
int rotate = 0;
try
{
File imageFile = new File(imahePath);
ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

switch (orientation)
{
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
return Bitmap.createBitmap(rotattedBitmap, 0, 0, rotattedBitmap.getWidth(), rotattedBitmap.getHeight(), matrix,
true);
}

It takes two arguments, image path and the bitmap image.

Try this method before sending the images to the server.

PHP on Webserver to send an image to another server and get back result

Sorry for the wait.
This is the script in WS that will receive the file from the client and will send it to GPU server. Notice I changed how the file is sent through curl (it was incorrect):

<?php

$ds = DIRECTORY_SEPARATOR;
$storeFolder = 'uploads';

if (!empty($_FILES)) {
$tempFile = $_FILES['file']['tmp_name'];
$targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds;
$targetFile = $targetPath. $_FILES['file']['name'];
move_uploaded_file($tempFile,$targetFile);
}

if(!cURLcheckBasicFunctions() )
{ echo "UNAVAILABLE: cURL Basic Functions"; }

// $url = "129.132.102.52/process.php";
$url = "dump_test.php";

$file = new CURLFile($tempFile);

$ch = curl_init();

curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => $file,
]);

/**
* As you can see in the script below, the GPU will echo the processed
* file and we will capture it here.
*/
$processedImage = curl_exec($ch);
curl_close($ch);

/**
* And now you can do anything with the processed file.
* For example, let's save it into a file.
*/
file_put_contents('processed_image.jpg', $processedImage);

function cURLcheckBasicFunctions() {
if( !function_exists("curl_init") &&
!function_exists("curl_setopt") &&
!function_exists("curl_exec") &&
!function_exists("curl_close") ) return false;
else return true;
}

And here's the script in the GPU server (this would be process.php):

<?php

$tempFile = $_FILES['file']['tmp_name'];

// Here you would process the file....

// Let's pretend you have the full path to the processed image in the $processedFilePath var.
// Now we will output the processed file contents so the WS server will receive it.

// The header isn't necessary but let's put it.
header('Content-Type: image/jpg');

echo file_get_contents($processedFilePath);

This script will work on PHP 5.5+. If you're using an older version, we would have to change the way the file is sent in the WS script.

Hope this is what you're looking for.

Server for displaying pictures in web browser

You can do it, by converting the image to base64 and display it in a html img tag.

1) Use the System.Drawing library to get the picture as a byte array

Image image = Image.FromFile("test-img.jpg");
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] imgBytes = ms.ToArray();

2) After you need to convert it to a base64 string

string base64 = Convert.ToBase64String(imgBytes);

3) Then you create the html response text

string html = $"<html><img src=\"data: image / png; base64, {base64} \"></html>";

4) Now you can write this text to the output stream

Stream stream = kontekst.Response.OutputStream;
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine(html);

So the full working code looks like this

static void Main(string[] args)
{
HttpListener listen = new HttpListener();
string url = "http://localhost";
string port = "";
Console.Write("Nastavite port:");
port = Console.ReadLine();
url = url + ":" + port + "/geoserver/";
listen.Prefixes.Add(url);
listen.Start();

while (true)
{
Console.WriteLine("Cakam...");
HttpListenerContext kontekst = listen.GetContext();

kontekst.Response.StatusCode = (int)HttpStatusCode.OK;

using (Stream stream = kontekst.Response.OutputStream)
using (Image image = Image.FromFile("test-img.jpg"))
using (MemoryStream ms = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
{
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
string base64 = Convert.ToBase64String(ms.ToArray());
writer.WriteLine($"<html><img src=\"data: image / png; base64, {base64} \"></html>");
}

Console.WriteLine("Sporočilo poslano");
}
}


Related Topics



Leave a reply



Submit