I'm using those methods to upload files,
Client Side:
private void Add(object sender, MouseButtonEventArgs e)
{
OpenFileDialog OFD = new OpenFileDialog();
OFD.Multiselect = true;
OFD.Filter = "Python (*.py)|*.py";
bool? Result = OFD.ShowDialog();
if (Result != null && Result == true)
foreach (var File in OFD.Files)
mylistbox.Items.Add(File);
}
private void Submit(object sender, MouseButtonEventArgs e)
{
foreach (var File in mylistbox.Items)
Process(((FileInfo)File).Name.Replace(((FileInfo)File).Extension, string.Empty), ((FileInfo)File).OpenRead());
}
private void Process(string File, Stream Data)
{
UriBuilder Endpoint = new UriBuilder("http://localhost:5180/Endpoint.ashx");
Endpoint.Query = string.Format("File={0}", File);
WebClient Client = new WebClient();
Client.OpenWriteCompleted += (sender, e) =>
{
Send(Data, e.Result);
e.Result.Close();
Data.Close();
};
Client.OpenWriteAsync(Endpoint.Uri);
}
private void Send(Stream Input, Stream Output)
{
byte[] Buffer = new byte[4096];
int Flag;
while ((Flag = Input.Read(Buffer, 0, Buffer.Length)) != 0)
{
Output.Write(Buffer, 0, Flag);
}
}
Server Side:
public void ProcessRequest(HttpContext Context)
{
using (FileStream Stream = File.Create(Context.Server.MapPath("~/" + Context.Request.QueryString["File"].ToString() + ".py")))
{
Save(Context.Request.InputStream, Stream);
}
}
private void Save(Stream Input, FileStream Output)
{
byte[] Buffer = new byte[4096];
int Flag;
while ((Flag = Input.Read(Buffer, 0, Buffer.Length)) != 0)
{
Output.Write(Buffer, 0, Flag);
}
}
My problem is that uploaded files have different Creation, Modification & Access Dates.
Why ?
When you upload a file, you are essentially creating a new file, with duplicated contents.
From your code:
using (FileStream Stream = File.Create(Context.Server.MapPath("~/" + Context.Request.QueryString["File"].ToString() + ".py")))
{
Save(Context.Request.InputStream, Stream);
}
The File.Create is responsible for the new dates.
See this answer for information on preserving the dates.
Related
I'm trying to limit file download a file at a time using System.Windows.Forms.WebBrowser or System.Windows.Controls.WebBrowser.
I try to catch this at System.Windows.Forms.WebBrowser.FileDowload event, but can't know when the file is completely downloaded.
Is there any way to catch when is the file download completed at Windows.Forms.WebBrowser or Windows.Controls.WebBrowser.
Thanks.
void descargaCompleta(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// When the download is complete
descargando = false;
}
void solo1Descarga (object sender, System.EventArgs e)
{
System.Windows.Forms.WebBrowser web = (System.Windows.Forms.WebBrowser)sender;
// Ask for Mutex
descargas.WaitOne();
descargando = true;
while (descargando)
;
descargas.ReleaseMutex();
}
// FunciĆ³n que Modifica la GUI
private void UpadteTabs()
{
WindowsFormsHost contWeb = new WindowsFormsHost();
System.Windows.Forms.WebBrowser nav = new System.Windows.Forms.WebBrowser();
// I set the Events to WebBrowser
nav.FileDownload += new EventHandler (solo1Descarga);
nav.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler (descargaCompleta);
}
Note: "download a file at a time" means that a download single can be at the same time.
For example, if you are trying to download a mega file and an image, 1 of the files needs to wait to the other finish
You can use WebReponse to download file
WebRequest request = WebRequest.Create(fileUri);
WebResponse response = request.GetResponse();
DownLoadFile(response, response.ContentLength);
private void DownLoadFile(HttpWebResponse response, long contentLength)
{
var respContentType = response.ContentType.ToUpper();
using (var fileStream = File.OpenWrite(fileName))
{
using (var responseStream = response.GetResponseStream())
{
var buffer = new byte[1024];
int bytesRead;
int offset = 0;
//Thread.Sleep(100);
while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) != 0)
{
fileStream.Write(buffer, 0, bytesRead);
offset += bytesRead;
}
if (offset != response.ContentLength)
{
//return string.Format("Only downloaded {0} of {1} bytes", offset, response.ContentLength));
throw new ApplicationException(string.Format("Only downloaded {0} of {1} bytes",
offset, response.ContentLength));
}
}
}
}
Alternativly write a while loop to read the binary data
public void DownloadFile(Uri uri, string filePathToSave)
{
var downloadedData = webClient.DownloadData(uri);
while (downloadedData.Length == 0)
{
Thread.Sleep(2000);
downloadedData = webClient.DownloadData(uri);
}
Stream file = File.Open(filePathToSave, FileMode.Create);
file.Write(downloadedData, 0, downloadedData.Length);
file.Close();
}
I have created a Form Application to Extracted Image , I have searched many posts , till Now I am able to download into the MemoryStream (Byte Array ).
I am not able to save that byte array into file system and check the image size ....
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public List<string> FetchImages(string Url)
{
List<string> imageList = new List<string>();
if (!Url.StartsWith("http://") && !Url.StartsWith("https://"))
Url = "http://" + Url;
string responseUrl = string.Empty;
string htmlData = ASCIIEncoding.ASCII.GetString(DownloadData(Url, out responseUrl));
if (responseUrl != string.Empty)
Url = responseUrl;
if (htmlData != string.Empty)
{
string imageHtmlCode = "<img";
string imageSrcCode = #"src=""";
int index = htmlData.IndexOf(imageHtmlCode);
while (index != -1)
{
htmlData = htmlData.Substring(index);
int brackedEnd = htmlData.IndexOf('>'); //make sure data will be inside img tag
int start = htmlData.IndexOf(imageSrcCode) + imageSrcCode.Length;
int end = htmlData.IndexOf('"', start + 1);
if (end > start && start < brackedEnd)
{
string loc = htmlData.Substring(start, end - start);
imageList.Add(loc);
}
if (imageHtmlCode.Length < htmlData.Length)
index = htmlData.IndexOf(imageHtmlCode, imageHtmlCode.Length);
else
index = -1;
}
for (int i = 0; i < imageList.Count; i++)
{
string img = imageList[i];
string baseUrl = GetBaseURL(Url);
if ((!img.StartsWith("http://") && !img.StartsWith("https://"))
&& baseUrl != string.Empty)
img = baseUrl + "/" + img.TrimStart('/');
imageList[i] = img;
}
}
return imageList;
}
private byte[] DownloadData(string Url)
{
string empty = string.Empty;
return DownloadData(Url, out empty);
}
private byte[] DownloadData(string Url, out string responseUrl)
{
byte[] downloadedData = new byte[0];
try
{
WebRequest req = WebRequest.Create(Url);
WebResponse response = req.GetResponse();
Stream stream = response.GetResponseStream();
responseUrl = response.ResponseUri.ToString();
byte[] buffer = new byte[1024];
MemoryStream memStream = new MemoryStream();
while (true)
{
int bytesRead = stream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
break;
}
else
{
memStream.Write(buffer, 0, bytesRead);
}
}
downloadedData = memStream.ToArray();
stream.Close();
memStream.Close();
}
catch (Exception)
{
responseUrl = string.Empty;
return new byte[0];
}
return downloadedData;
}
private Image ImageFromURL(string Url)
{
byte[] imageData = DownloadData(Url);
Image img = null;
try
{
MemoryStream stream = new MemoryStream(imageData);
img = Image.FromStream(stream);
stream.Close();
}
catch (Exception)
{
}
return img;
}
private string GetBaseURL(string Url)
{
int inx = Url.IndexOf("://") + "://".Length;
int end = Url.IndexOf('/', inx);
string baseUrl = string.Empty;
if (end != -1)
return Url.Substring(0, end);
else
return string.Empty;
}
private void btnGetImages_Click(object sender, EventArgs e)
{
this.Cursor = Cursors.WaitCursor;
listImages.Items.Clear();
foreach (string image in FetchImages(txtURL.Text))
{
listImages.Items.Add(image);
}
this.Cursor = Cursors.Default;
}
private void btnView_Click(object sender, EventArgs e)
{
if (listImages.SelectedIndex != -1)
picImage.Image = ImageFromURL(listImages.SelectedItem.ToString());
}
private void btnSave_Click(object sender, EventArgs e)
{
}
private void btnDownload_Click(object sender, EventArgs e)
{
DownloadData(txtURL.Text);
}
.. I am trying to save the memroy stream into hard drive but still not getting exact code ,
i think this code needs some additional changes
MemoryStream memStream = new MemoryStream();
while (true)
{
//Try to read the data
int bytesRead = stream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
break;
}
else
{
//Write the downloaded data
memStream.Write(buffer, 0, bytesRead);
}
}
Any Help will be appreciated
If you want to save the Byte[] array to a file,
Syntax : File.WriteAllBytes(string path, byte[] bytes)
Eg : File.WriteAllBytes("Foo.txt", arrBytes); // Requires System.IO
refer this link for more info http://msdn.microsoft.com/en-us/library/system.io.file.writeallbytes.aspx
If you want to convert the Byte back to image and save to the drive.
Eg:
byte[] bitmap = YourImage();
using(Image image = Image.FromStream(new MemoryStream(bitmap)))
{
image.Save("image.jpg", ImageFormat.Jpeg);
}
I try to convert zip file to byte[] and write it to a text file.
int BufferSize=65536;
private void button1_Click(object sender, EventArgs e)
{
DialogResult re = openFileDialog1.ShowDialog();
if (re == DialogResult.OK)
{
string fileName = openFileDialog1.FileName;
try
{
byte[] bytes = File.ReadAllBytes(fileName);
File.WriteAllBytes(#"F:\Info.txt", bytes);
}
catch (Exception) { }
}
}
Then I try to convert those byte to zip file. But I can't do it.
My code is here:
private void button2_Click(object sender, EventArgs e)
{
DialogResult re = openFileDialog1.ShowDialog();
if (re == DialogResult.OK)
{
string fileName = openFileDialog1.FileName;
try
{
byte[] bytes = File.ReadAllBytes(fileName);
using (var mstrim = new MemoryStream(bytes))
{
using (var inStream = new GZipStream(mstrim, CompressionMode.Compress))
{
using (var outStream = File.Create("Tax.Zip"))
{
var buffer = new byte[BufferSize];
int readBytes;
while ((readBytes = inStream.Read(buffer, 0, BufferSize)) != 0)
{
outStream.Write(buffer, 0, readBytes);
}
}
}
}
}
catch (Exception) { }
}
}
Error:File Mode not valid.
What File Mode is needed and how can I accomplish what I described?
Just try this.
byte[] data = File.ReadAllBytes("D:\\z.7z");
File.WriteAllBytes("D:\\t.txt", data); // Requires System.IO
byte[] newdata = File.ReadAllBytes("D:\\t.txt");
File.WriteAllBytes("D:\\a.7z", newdata); // Requires System.IO
Try this,
private void button1_Click(object sender, EventArgs e)
{
byte[] arr;
MemoryStream ms = new MemoryStream();
arr = File.ReadAllBytes("C:\\asik.zip");
File.WriteAllBytes(#"D:\\asik.txt", arr);
ms.Close();
FileStream stream = File.OpenRead(#"D:\\asik.txt");
byte[] fileBytes = new byte[stream.Length];
stream.Read(fileBytes, 0, fileBytes.Length);
stream.Close();
MemoryStream ms1 = new MemoryStream(fileBytes);
CreateToMemoryStream(ms1, #"D:\\asik.zip");
ms1.Close();
}
public void CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName)
{
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
ZipEntry newEntry = new ZipEntry(zipEntryName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
//outputMemStream.Position = 0;
//return outputMemStream;
//// Alternative outputs:
//// ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
//byte[] byteArrayOut = outputMemStream.ToArray();
//// GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
//byte[] byteArrayOut2 = outputMemStream.GetBuffer();
//long len = outputMemStream.Length;
}
You're using GZipStream, which is used for GZip files, not (PK-)Zip files. This isn't going to work, obviously. Try the ZipFile class instead (though sadly, it doesn't work on streams, just files).
Apart from simply being a different file format, the big difference is that GZip is for compression only, while Zip is also an archive (that is, it can contain multiple files).
public class BytesVal {
public static void main(String[] args) throws IOException, MoreZipException {
// TODO Auto-generated method stub
File file = new File("F:\\ssd\\doc\\");
System.out.println("Byte inside the Zip file is" + BytesVal.getAllBytes(file));
}
public static byte[] getAllBytes(File folderName) throws IOException, MoreZipException {
String[] sourceFiles = null;
if (folderName.isDirectory()) {
sourceFiles = folderName.list();
if (sourceFiles.length > 1) {
throw new MoreZipException(sourceFiles.length);
}
}
byte[] bytes = null;
Path filePath = Paths.get("F:/ssd/doc/" + sourceFiles[0]);
bytes = Files.readAllBytes(filePath);
return bytes;
}
}
I am developing an application for windows phone 7.From here I want to upload an image file to the remote server.I am using the following code to receive the file at my receiving end:
if (Request.Files.Count > 0)
{
string UserName = Request.QueryString["SomeString"].ToString();
HttpFileCollection MyFilecollection = Request.Files;
string ImageName = System.Guid.NewGuid().ToString() + MyFilecollection[0].FileName;
MyFilecollection[0].SaveAs(Server.MapPath("~/Images/" + ImageName));
}
Now my problem is, how can I post the file from my windows phone 7 platform (using PhotoChooserTask).I have tried the following code but with no success.(the following code is called from the PhotoChooserTask completed event handler.
private void UploadFile(string fileName, Stream data)
{
char[] ch=new char[1];
ch[0] = '\\';
string [] flname=fileName.Split(ch);
UriBuilder ub = new UriBuilder("http://www.Mywebsite.com?SomeString="+ussi );
ub.Query = string.Format("name={0}", flname[6]);
WebClient c = new WebClient();
c.OpenWriteCompleted += (sender, e) =>
{
PushData(data, e.Result);
e.Result.Close();
data.Close();
};
c.OpenWriteAsync(ub.Uri);
}
private void PushData(Stream input, Stream output)
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, bytesRead);
}
}
Please help me out to get out from this problem.
Thanks
I was able to get this working, but not using the Files collection. From my post at http://chriskoenig.net/2011/08/19/upload-files-from-windows-phone/:
Client Code
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void SelectButton_Click(object sender, RoutedEventArgs e)
{
PhotoChooserTask task = new PhotoChooserTask();
task.Completed += task_Completed;
task.Show();
}
private void task_Completed(object sender, PhotoResult e)
{
if (e.TaskResult != TaskResult.OK)
return;
const int BLOCK_SIZE = 4096;
Uri uri = new Uri("http://localhost:4223/File/Upload", UriKind.Absolute);
WebClient wc = new WebClient();
wc.AllowReadStreamBuffering = true;
wc.AllowWriteStreamBuffering = true;
// what to do when write stream is open
wc.OpenWriteCompleted += (s, args) =>
{
using (BinaryReader br = new BinaryReader(e.ChosenPhoto))
{
using (BinaryWriter bw = new BinaryWriter(args.Result))
{
long bCount = 0;
long fileSize = e.ChosenPhoto.Length;
byte[] bytes = new byte[BLOCK_SIZE];
do
{
bytes = br.ReadBytes(BLOCK_SIZE);
bCount += bytes.Length;
bw.Write(bytes);
} while (bCount < fileSize);
}
}
};
// what to do when writing is complete
wc.WriteStreamClosed += (s, args) =>
{
MessageBox.Show("Send Complete");
};
// Write to the WebClient
wc.OpenWriteAsync(uri, "POST");
}
}
Server Code
public class FileController : Controller
{
[HttpPost]
public ActionResult Upload()
{
string filename = Server.MapPath("/Uploads/" + Path.GetRandomFileName();
try
{
using (FileStream fs = new FileStream(filename), FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
using (BinaryReader br = new BinaryReader(Request.InputStream))
{
long bCount = 0;
long fileSize = br.BaseStream.Length;
const int BLOCK_SIZE = 4096;
byte[] bytes = new byte[BLOCK_SIZE];
do
{
bytes = br.ReadBytes(BLOCK_SIZE);
bCount += bytes.Length;
bw.Write(bytes);
} while (bCount < fileSize);
}
}
}
return Json(new { Result = "Complete" });
}
catch (Exception ex)
{
return Json(new { Result = "Error", Message = ex.Message });
}
}
}
Note that I'm using ASP.NET MVC to receive my file, but you should be able to use the same, core logic with WebForms.
/chris
I am using VSTS 2008 + C# + .Net 3.5 + ASP.Net + IIS 7.0 to develop a console application at client side to upload a file, and at server side I receive this file using an aspx file.
From client side, I always notice (from console output) the upload percetage of the file increase from 1% to 50%, then to 100% suddenly. Any ideas what is wrong?
Here is my client side code,
class Program
{
private static WebClient client = new WebClient();
private static ManualResetEvent uploadLock = new ManualResetEvent(false);
private static void Upload()
{
try
{
Uri uri = new Uri("http://localhost/Default.aspx");
String filename = #"C:\test\1.dat";
client.Headers.Add("UserAgent", "TestAgent");
client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback);
client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadFileCompleteCallback);
client.UploadFileAsync(uri, "POST", filename);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace.ToString());
}
}
public static void UploadFileCompleteCallback(object sender, UploadFileCompletedEventArgs e)
{
Console.WriteLine("Completed! ");
uploadLock.Set();
}
private static void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e)
{
Console.WriteLine (e.ProgressPercentage);
}
static void Main(string[] args)
{
Upload();
uploadLock.WaitOne();
return;
}
}
Here is my server side code,
protected void Page_Load(object sender, EventArgs e)
{
string agent = HttpContext.Current.Request.Headers["UserAgent"];
using (FileStream file = new FileStream(#"C:\Test\Agent.txt", FileMode.Append, FileAccess.Write))
{
byte[] buf = Encoding.UTF8.GetBytes(agent);
file.Write(buf, 0, buf.Length);
}
foreach (string f in Request.Files.AllKeys)
{
HttpPostedFile file = Request.Files[f];
file.SaveAs("C:\\Test\\UploadFile.dat");
}
}
thanks in advance,
George
This is a known bug in the WebClient class. It will be fixed in .NET 4.0. Until then you could use HttpWebRequest to implement this functionality.
UPDATE: Here's an example of using synchronous HttpWebRequest to upload a file and track the progress:
public sealed class Uploader
{
public const int CHUNK_SIZE = 1024; // 1 KB
public void Upload(string url, string filename, Stream streamToUpload, Action<int> progress)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
string boundary = string.Format("---------------------{0}", DateTime.Now.Ticks.ToString("x"));
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
request.KeepAlive = true;
using (var requestStream = request.GetRequestStream())
{
var header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", boundary, filename);
var headerBytes = Encoding.ASCII.GetBytes(header);
requestStream.Write(headerBytes, 0, headerBytes.Length);
byte[] buffer = new byte[CHUNK_SIZE];
int bytesRead;
long total = streamToUpload.Length;
long totalBytesRead = 0;
while ((bytesRead = streamToUpload.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytesRead += bytesRead;
progress((int)(100 * totalBytesRead / total));
byte[] actual = new byte[bytesRead];
Buffer.BlockCopy(buffer, 0, actual, 0, bytesRead);
requestStream.Write(actual, 0, actual.Length);
}
}
using (var response = request.GetResponse()) { }
}
}
class Program
{
static void Main(string[] args)
{
var url = "http://localhost:2141/Default.aspx";
var filename = "1.dat";
var uploader = new Uploader();
using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
uploader.Upload(url, filename, fileStream, progress => Console.WriteLine("{0}% of \"{1}\" uploaded to {2}", progress, filename, url));
}
}
}
You can read webclient.UploadProgressChanged code.Then you will know the reason.Code below.
private void PostProgressChanged(AsyncOperation asyncOp, WebClient.ProgressData progress)
{
if (asyncOp == null || progress.BytesSent + progress.BytesReceived <= 0L)
return;
if (progress.HasUploadPhase)
{
int progressPercentage = progress.TotalBytesToReceive >= 0L || progress.BytesReceived != 0L
? (progress.TotalBytesToSend < 0L
? 50
: (progress.TotalBytesToReceive == 0L
? 100
: (int) (50L*progress.BytesReceived/progress.TotalBytesToReceive + 50L)))
: (progress.TotalBytesToSend < 0L
? 0
: (progress.TotalBytesToSend == 0L ? 50 : (int) (50L*progress.BytesSent/progress.TotalBytesToSend)));
asyncOp.Post(this.reportUploadProgressChanged,
(object)
new UploadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState,
progress.BytesSent, progress.TotalBytesToSend, progress.BytesReceived,
progress.TotalBytesToReceive));
}
else
{
int progressPercentage = progress.TotalBytesToReceive < 0L
? 0
: (progress.TotalBytesToReceive == 0L
? 100
: (int) (100L*progress.BytesReceived/progress.TotalBytesToReceive));
asyncOp.Post(this.reportDownloadProgressChanged,
(object)
new DownloadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState,
progress.BytesReceived, progress.TotalBytesToReceive));
}
}
This beheavior is by design, its 50% upload the file and 50% the response of the server.
Not a bug.