I want to read mp3 file from external url and hide url path for client in my website.
I'm using this code:
//Create a stream for the file
Stream stream = null;
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 10000;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
// The number of bytes read
try
{
//Create a WebRequest to get the file
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create("http://www.alsacreations.fr/mp3/everywhere.mp3");
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Current.Response;
//Indicate the type of data being sent
resp.ContentType = "application/octet-stream";
//Name the file
string fileName = "everywhere.mp3";
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName);
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
if (resp.IsClientConnected)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.OutputStream.Write(buffer, 0, length);
// Flush the data
resp.Flush();
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
This code is work correctly, My question is for download this mp3 file(http://www.alsacreations.fr/mp3/everywhere.mp3) use My Site's BandWidth or not?
Related
I have create a WCF Service that allows uploading large files via BasicHttpBinding using streaming and it is working great! I would like to extended this to show a progress bar (UIProgressView) so that when a large file is being uploaded in 65k chunks, the user can see that it is actively working.
The client code calling the WCF Service is:
BasicHttpBinding binding = CreateBasicHttp ();
BTSMobileWcfClient _client = new BTSMobileWcfClient (binding, endPoint);
_client.UploadFileCompleted += ClientUploadFileCompleted;
byte[] b = File.ReadAllBytes (zipFileName);
using (new OperationContextScope(_client.InnerChannel)) {
OperationContext.Current.OutgoingMessageHeaders.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader("SalvageId","",iBTSSalvageId.ToString()));
OperationContext.Current.OutgoingMessageHeaders.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader("FileName","",Path.GetFileName(zipFileName)));
OperationContext.Current.OutgoingMessageHeaders.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader("Length","",b.LongLength));
_client.UploadFileAsync(b);
}
On the server side, I read the file stream in 65k chuncks and do report back to the calling routine "bytes read", etc. A snippet of code for that is:
using (FileStream targetStream = new FileStream(filePath, FileMode.CreateNew,FileAccess.Write)) {
//read from the input stream in 65000 byte chunks
const int chunkSize = 65536;
byte[] buffer = new byte[chunkSize];
do {
// read bytes from input stream
int bytesRead = request.FileData.Read(buffer, 0, chunkSize);
if (bytesRead == 0) break;
// write bytes to output stream
targetStream.Write(buffer, 0, bytesRead);
} while (true);
targetStream.Close();
}
But I don't know how to hook into the callback on the Xamarin side to receive the "bytes read" versus "total bytes to send" so I can update the UIProgressView.
Has anyone tried this or is this even possible?
Thanks In Advance,
Bo
I'd like to use HttpResponse.OutputStream together with ContentResult so that I can Flush from time to time to avoid using too much RAM by .Net.
But all examples with MVC FileStreamResult, EmptyResult, FileResult, ActionResult, ContentResult show code that gets all the data into memory and passes to one of those. Also one post suggest that returning EmptyResult together with using HttpResponse.OutputStream is bad idea. How else can I do that in MVC ?
What is the right way to organize flushable output of big data (html or binary) from MVC server ?
Why is returning EmptyResult or ContentResult or FileStreamResult a bad idea ?
You would want to use FileStreamResult if you already had a stream to work with. A lot of times you may only have access to the file, need to build a stream and then output that to the client.
System.IO.Stream iStream = null;
// Buffer to read 10K bytes in chunk:
byte[] buffer = new Byte[10000];
// Length of the file:
int length;
// Total bytes to read:
long dataToRead;
// Identify the file to download including its path.
string filepath = "DownloadFileName";
// Identify the file name.
string filename = System.IO.Path.GetFileName(filepath);
try
{
// Open the file.
iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
System.IO.FileAccess.Read,System.IO.FileShare.Read);
// Total bytes to read:
dataToRead = iStream.Length;
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Response.IsClientConnected)
{
// Read the data in buffer.
length = iStream.Read(buffer, 0, 10000);
// Write the data to the current output stream.
Response.OutputStream.Write(buffer, 0, length);
// Flush the data to the HTML output.
Response.Flush();
buffer= new Byte[10000];
dataToRead = dataToRead - length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
catch (Exception ex)
{
// Trap the error, if any.
Response.Write("Error : " + ex.Message);
}
finally
{
if (iStream != null)
{
//Close the file.
iStream.Close();
}
Response.Close();
}
Here is the microsoft article explaining the above code.
I am using this Utility
public class Util_ImageLoader {
public static Bitmap _bmap;
Util_ImageLoader(String url) {
HttpConnection connection = null;
InputStream inputStream = null;
EncodedImage bitmap;
byte[] dataArray = null;
try {
connection = (HttpConnection) Connector.open(url + Util_GetInternet.getConnParam(), Connector.READ,
true);
inputStream = connection.openInputStream();
byte[] responseData = new byte[10000];
int length = 0;
StringBuffer rawResponse = new StringBuffer();
while (-1 != (length = inputStream.read(responseData))) {
rawResponse.append(new String(responseData, 0, length));
}
int responseCode = connection.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + responseCode);
}
final String result = rawResponse.toString();
dataArray = result.getBytes();
} catch (final Exception ex) {
}
finally {
try {
inputStream.close();
inputStream = null;
connection.close();
connection = null;
} catch (Exception e) {
}
}
bitmap = EncodedImage
.createEncodedImage(dataArray, 0, dataArray.length);
int multH;
int multW;
int currHeight = bitmap.getHeight();
int currWidth = bitmap.getWidth();
multH = Fixed32.div(Fixed32.toFP(currHeight), Fixed32.toFP(currHeight));// height
multW = Fixed32.div(Fixed32.toFP(currWidth), Fixed32.toFP(currWidth));// width
bitmap = bitmap.scaleImage32(multW, multH);
_bmap = bitmap.getBitmap();
}
public Bitmap getbitmap() {
return _bmap;
}
}
When I call it in a listfield which contains 10 childs, then the log keeps saying failed to allocate timer 0: no slots left.
This means the memory is being used up and no more memory to allocate again and as a result my main screen cannot start.
At the same time you have the following objects in memory:
// A buffer of about 10KB
byte[] responseData = new byte[10000];
// A string buffer which will grow up to the total response size
rawResponse.append(new String(responseData, 0, length));
// Another string the same length that string buffer
final String result = rawResponse.toString();
// Now another buffer the same size of the response.
dataArray = result.getBytes();
It total, if you downloaded n ascii chars, you have simultaneously 10KB, plus 2*n bytes in the first unicode string buffer, plus 2*n bytes in the result string, plus n bytes in dataArray. If I'm not wrong, that sums up to 5n + 10k. There's room for optimization.
Some improvements would be:
Check response code first, and then read the stream if response code is HTTP 200. No need to read if server returned an error.
Get rid of strings. No need to convert to string if after that you are converting again to bytes.
If images are large, don't store them in RAM while downloading. Instead, open a FileOutputStream and write to a temporary file as you read from input stream. Then, if temporary images are still large enough to be displayed, downscale them.
From the simulator, this all works.
I'm using wifi on the device as i'm assuming it's the most stable.
The problem occurs when i try to post more than 1.5K of urlencoded data.
If i send less then it's fine.
It seems to hang the .flush command();
It works on a physical 9700, so i'm presuming that it's possibly device specific
In the example below i'm using form variables, but i've also tried posting the content type json, but still had the same issue
I've written a small testapp, and using the main thread so i know that it's not threads getting confused
If anyone has any ideas that would be great.
private String PostEventsTest()
{
String returnValue = "Error";
HttpConnection hc = null;
DataInputStream dis = null;
DataOutputStream dos = null;
StringBuffer messagebuffer = new StringBuffer();
URLEncodedPostData postValuePairs;
try
{
postValuePairs = new URLEncodedPostData(null, false);
postValuePairs.append("DATA",postData);// postData);
hc = (HttpConnection) Connector.open(postURL, Connector.READ_WRITE);
hc.setRequestMethod(HttpConnection.POST);
hc.setRequestProperty("User-Agent", "BlackBerry");
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
hc.setRequestProperty("Content-Length", Integer.toString(postValuePairs.getBytes().length));
//hc.setRequestProperty("Content-Length", Integer.toString(postData.length()));
dos = hc.openDataOutputStream();
dos.write(postValuePairs.getBytes());
dos.flush();
dos.close();
// Retrieve the response back from the servlet
dis = new DataInputStream(hc.openInputStream());
int ch;
// Check the Content-Length first
long len = hc.getLength();
if (len != -1)
{
for (int i = 0; i < len; i++)
if ((ch = dis.read()) != -1)
messagebuffer.append((char) ch);
}
else
{ // if the content-length is not available
while ((ch = dis.read()) != -1)
messagebuffer.append((char) ch);
}
dis.close();
returnValue = "Yahoo";
}
catch (Exception ex)
{
returnValue = ex.toString();
ex.printStackTrace();
}
return returnValue;
}
Instead of data streams you should just use the regular input and output streams. So instead of hc.openDataOutputStream() use hc.openOutputStream(). Data streams are for serializing Java objects to a stream, but you just want to write the raw bytes to the stream -- so a regular outputstream is what you want. Same for reading the response - just use the inputstream returned by hc.openInputStream()
I want to display the content of any given URL as a string.....
Can any one give some sample code here?
String url = "http://google.com";
HttpConnection _conn = (HttpConnection) Connector.open(url);
int rc = _conn.getResponseCode();
System.out.println("RC : " + rc);
if(rc != 200)
return;
InputStream is = null;
byte[] result = null;
is = _conn.openInputStream();
// Get the ContentType
String type = _conn.getType();
// Get the length and process the data
int len = (int)_conn.getLength();
if (len > 0) { // If data lenght is defined
int actual = 0;
int bytesread = 0;
result = new byte[len];
while ((bytesread != len) && (actual != -1)) {
actual = is.read(result, bytesread, len - bytesread);
bytesread += actual;
}
}else { // If no data lenght is not defined in HTTP response
// Data accumulation buffer (for whole data)
NoCopyByteArrayOutputStream outputStream = new NoCopyByteArrayOutputStream(1024);
// Receive buffer (for each portion of data)
byte[] buff = new byte[1024];
while ((len = is.read(buff)) > 0) {
// Write received portion of data into accumulation stream
outputStream.write(buff, 0, len);
}
result = outputStream.toByteArray();
System.out.println(new String(result));
}