I have a .NET MVC project and I'm trying to download a file from temporary folder. Here is my view code:
window.open('#Url.Action("DownloadDocument", "Controller")?fileName=' + fileName, '_blank');
And here is my controller code:
public FileResult DownloadDocument(string fileName)
{
string path = Web.Common.Properties.Settings.Default.TempDocPath + "OpenTable\\";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return File(fileName, "application/xml", fileName + ".xml");
}
This code works on IIS and file is being downloaded. But I'm getting 500 error when trying to download it from remote server.
This site can’t be reached
The webpage at <...> might be temporarily down or it may have moved permanently to a new web address.
ERR_INVALID_RESPONSE
And the worst part is that there are some almost exact code snippets in the system which are working in both IIS and remote server.
Any suggestions what could be done?
UPDATE
Good news. When I tried postman it threw a file not found error with wrong path. It's an easy fix:
return File(Path.Combine(path, fileName), "application/xml", fileName + ".xml");
So it puzzles me... How and why it was working locally on IIS with wrong path?
You need to create your temp folder inside the root folder of your web app, for example ~/Temp, then use below code to access to that folder instead of Web.Common.Properties.Settings.Default.TempDocPath, I think this maybe just a constant.
System.Web.Hosting.HostingEnvironment.MapPath("~/Temp")
Related
Allowing POST method to an HTML page in ASP.NET MVC
I am using ASP.NET with MVC 5.2 and I am integrating RoxyFileManager to my CKEditor.
The integration was fine, the problem is when I try to upload some file to my web server, I got this error:
NetworkError: 405 Method Not Allowed - http://localhost:35418/FileManager/index.html?...
The RoxyFileManager uses the POST method to upload the file and my webserver does not accept it. I can't figure out how can I fix it.
If I put manually an image to my directory I can see it in the file manager, also I can create and exclude folders there.
To clarify my question: I want to know how can I make my webserver accept the POST method to a HTML page, just it. All the relevant information are above. I have a HTML page and want to make it accept POST.
#UPDATE:
I've figured out the problem is a browser issue.
In Google Chrome everything works fine;
In Firefox I get the error above;
In IE things seens to work fine, but it have cache problems (I can upload and edit previously sent files, but I can't see the changes neither the recent file uploads until cache expires);
I'll work on these problems and post the answer here, if successful.
To solve the IE bug it's simple but it's hard-work: You need to add in every ajax call of RoxyFileMan the line cache: false. You need to do it in every .js file on the RoxyFileMan folder.
Example:
$.ajax({
url: d, dataType: "json", async: true, success: function (h) {
for (i = 0; i < h.length; i++) { e.push(new File(h[i].p, h[i].s, h[i].t, h[i].w, h[i].h)) }
g.FilesLoaded(e)
},
error: function (h) { alert(t("E_LoadingAjax") + " " + d) },
cache: false
})
With this, all the ajax made by Roxy will have no cache, solving the IE issue.
To solve the Firefox bug I've changed this in the main.min.js:
BEFORE:
document.forms.addfile.action = RoxyFilemanConf.UPLOAD
AFTER:
$('form[name="addfile"]').attr('action', RoxyFilemanConf.UPLOAD);
I've found this solution here.
And now my file manager is working on all modern browsers.
I created a configuration file (Simple Text File) on my Google Drive and now I would like to read it from my Chrome Packaged Dart Application. But I'm not able to get more information of the file than it's name, size etc.
For accessing Google Drive I use the google_drive_v2_api.
Any suggestion on how to get the contents of my configuration file would be great! Thanks!
I just did some test in my own chrome app, uploading and downloading a simple file:
chrome.identity.getAuthToken(new chrome.TokenDetails(interactive: true ))
.then((token){
OAuth2 auth = new SimpleOAuth2(token);
var drive = new gdrive.Drive(auth)..makeAuthRequests=true;
drive.files.insert({},content:window.btoa('hello drive!')).then((sentMeta){
print("File sent! Now retrieving...");
drive.files.get(sentMeta.id).then((repliedMeta){
HttpRequest request = new HttpRequest()..open('GET', repliedMeta.downloadUrl)
..onLoad.listen((r)=>print('here is the result:'+r.target.responseText));
auth.authenticate(request).then((oAuthReq)=>oAuthReq.send());
});
});
});
It works, but the HttpRequest to get content back seems heavy...
But i really recommend you to a take look to chrome.storage.sync if your config file size is < to 4ko... If not, you could also use the chrome SyncFileSystem API... They are both easier to use, and SyncFileSystem use Drive as backend.
This page on downloading files talks through the process for getting the contents of a file.
Following the tutorial found on ASP.NET, implemented a Web API controller method for doing asynchronous file uploads that looks like this:
public 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);
// Read the form data and return an async task.
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
return Request.CreateResponse(HttpStatusCode.OK);
});
return task;
}
Uploading a file via a standard multipart HTML form works perfectly. However, when another developer attempts to upload a file via multipart form constructed by Flex's FileReference class, an error is thrown:
Unexpected end of MIME multipart stream. MIME multipart message is not complete.
I have no idea if the problem lies in Web API or Flex. I've found some sort of related fixes that had no affect (Multipart form POST using ASP.Net Web API), and more recently this one ("MIME multipart stream. MIME multipart message is not complete" error on webapi upload). If the second link holds true, does anyone know if it's out in the current release of Web API available via Nuget? The discussion was in May, the most recent release from Nuget was August, so I assume this fix was deployed already, and is not the root cause of my issue.
I had the same problem with MVC4, but Will is correct, add a name to your input.....
<input type="file" id="fileInput" name="fileInput"/>
and all the magic is back up and working!
I had the same problem with flex. And below is the code that solved it. Basically I used a custom stream to append the newline that asp.net web api is expecting.
Stream reqStream = Request.Content.ReadAsStreamAsync().Result;
MemoryStream tempStream = new MemoryStream();
reqStream.CopyTo(tempStream);
tempStream.Seek(0, SeekOrigin.End);
StreamWriter writer = new StreamWriter(tempStream);
writer.WriteLine();
writer.Flush();
tempStream.Position = 0;
StreamContent streamContent = new StreamContent(tempStream);
foreach(var header in Request.Content.Headers)
{
streamContent.Headers.Add(header.Key, header.Value);
}
// Read the form data and return an async task.
await streamContent.ReadAsMultipartAsync(provider);
Hope this helps.
Reading through your existing research and following through to the codeplex issue reported it looks like someone else confirmed this issue to still exist in September.
They believe that MVC 4 fails to parse uploads without a terminating "\r\n".
The issue is really simple but extremely hard to fix. The problem is that Uploadify does > not add an "\r\n" at the end of the MultiPartForm message
http://aspnetwebstack.codeplex.com/discussions/354215
It may be worth checking that the Flex upload adds the "\r\n"
For those landing here googling:
Unexpected end of MIME multipart stream. MIME multipart message is not complete.
Reading the request stream more than once will also cause this exception. I struggled with it for hours until I found a source explaining that the request stream only could be read once.
In my case, I combined trying to read the request stream using a MultipartMemoryStreamProvider and at the same time letting ASP.NET do some magic for me by specifying parameters (coming from the request body) for my api method.
Make sure the virtual directory ("~/App_Data" directory as below example) where the image files are first uploaded are physically existance. When you publish the project, it may not be in the output files.
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
I just removed my headers I was setting on my post method which ended up solving this issue.
The problem is this line:
string root = HttpContext.Current.Server.MapPath("~/App_Data");
It will only work in localhost, you can use HostingEnvironment.MapPath instead in any context where System.Web objects like HttpContext.Current are not available (e.g also from a static method).
var mappedPath = System.Web.Hosting.HostingEnvironment.MapPath("~/SomePath");
See also What is the difference between Server.MapPath and HostingEnvironment.MapPath?
Reference to this answer How to do a Server Map Path.
in my app user can upload images to server,and i put the uploaded file in upload folder like this
public
upload
but when i serve the
<img src='upload/image.jpg'/>
there is a 404 error.
i use express and use the
app.use(express.static(__dirname + '/public'));
does it mean i have to put all the uploaded in the public folder, what if there is so many images that the hard drive can not hold, can't i put the rest in a another server?
No you don't have to put all uploaded files to public folder.
Express allows to configure multiple middle-ware so you can add one more middle-ware to serve static content from the desired directory.
If you want directory to be specified in Url path then you can use directory mount feature like this !!
app.use('/upload',express.static(__dirname + '/upload'));
Ofcouse you can use other server to store uploaded files and you can retrieve those file by proxing request to it.
app.get('/upload/:fileName',function(req,res) {
var options = {
port: 80,
method : 'GET',
hostname : "localhost",
path : "/upload/" + req.params.fileName
};
var req = http.request(options,function(response) {
response.pipe(res);
});
req.on('error',function(err) {
res.statusCode = 404;
res.end("Error : file not found");
});
req.end();
});
This code will work not only when uploaded files are stored in the original server but also if you have files on some other server too !!
You can put the images in ./public/upload
Try using this:
<img src='/upload/image.jpg'/>
Notice the slash before upload. It could be that the problem isn't where you save the files, but rather how you're referencing them. If the page with the img tag isn't in your root directory, then the relative url upload/image.jpg won't work. You need to use /upload/image.jpg.
If you
app.use(express.static(__dirname + '/public'));
and ./public contains:
/img.png
/img2.png
/logo.png
yourapp.com/img.png will be img.png.
If you want yourapp.com/img.png to be a 404 and yourapp.com/public/img.png to be img.png, you need to replace
app.use(express.static(__dirname + '/public'));
with
app.use("/public",express.static(__dirname + '/public'));
I have a controller that needs to redirect after receiving a file. I have saved the file successfully on the server side. Now, the only things that is bogging me down is how do I redirect to another site while sending the uploaded file that was saved on the server? Any tips? I am desparate.
OK so here it is, first I save the file on serverB:
file.SaveAs(Server.MapPath("~/ImageCache/") + file.FileName);
WebClient client = new WebClient();
Then I do the post:
byte[] data;
client.Headers.Set(HttpRequestHeader.ContentType, "image/jpeg");
data = client.UploadFile("http://hostA.com/Search/", "POST", Server.MapPath("~/ImageCache/") + file.FileName);
return Redirect( WHAT DO I WRITE HERE??);
Need to get to the place where I find the other service showing me the page when it has received the file.
How are you uploading the file? If this is the usual case of an <input type="file" />, you can just return Redirect("new url"); within your action.
Edit:
If you want to relay this to another web service, you don't need to redirect. There should be some sort of upload method defined in the webservice (including what type of webservice would help). You should be able to call that like you would any other webservice method, probably specifying the FileContents byte[] as a parameter.