I am trying to download a .csv file on clicking the Download button in my jsp.The jsp code is like following......
<form:form method="POST" id="poCSVForm"
action="downloadPoCsv" commandName="poCSVcmd" modelAttribute="poCSVcmd">
<div class="content">
<fieldset>
<legend>Page Name</legend>
<div>
<div class="contentpane">
<table>
<tr>
<td><button type="submit" value="Download" id="downId" class="dwnldbtn">Download</button>
<button type="button" class="exit smallbtn" value="Exit">Exit</button></td>
</tr>
</table>
</div>
</div>
</fieldset>
</div>
</form:form>
Then my controller code is like this......
#RequestMapping(value = "/downloadPoCsv", method = RequestMethod.POST)
public void doPoCsvDownload(
#ModelAttribute("poCSVcmd") PurchaseOrderCSVBean poCsvBean,
Map<String, Object> model, HttpServletRequest req,HttpServletResponse response) throws IOException {
CSVWriter writer = null;
String filepath = null;
try {
HttpSession session = req.getSession();
Session hsession = (Session) session
.getAttribute(MOLConstants.HIBERNATE_SESSION_KEY);
filepath = "purchaseOrder" + new Date().getTime() + ".csv";
ServletContext context = req.getServletContext();
String realPath = context.getRealPath("");
System.out.println("appPath = " + realPath);
// construct the complete absolute path of the file
String fullPath = realPath + "\\stuff\\" + filepath;
System.out.println("fullPath = " + fullPath);
File downloadFile = new File(realPath);
try {
if (!downloadFile.exists()) {
if (downloadFile.mkdir()) {
} else {
throw new RuntimeException("Could not create directory");
}
}
} catch (Exception e) {
throw new RuntimeException();
}
String mimeType = context.getMimeType(fullPath); // get MIME type of the file
if (mimeType == null) {
mimeType = "application/octet-stream"; // set to binary type if MIME mapping not found
}
System.out.println("MIME type: " + mimeType);
// set content attributes for the response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
// set headers for the response
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"",downloadFile.getName());
response.setHeader(headerKey, headerValue);
List<PoCsvUploadView> csvDataList = poService.getPoCsvData(poCsvBean.getExp_ind(),poCsvBean.getStdt(),poCsvBean.getEnddt());
FileWriter fwriter = new FileWriter(fullPath);
writer = new CSVWriter(fwriter, ',', CSVWriter.NO_QUOTE_CHARACTER);
String[] header = new String[31];
header[0] = "COMPANY_CD";
.......
header[30] = "VENDOR_TYPE";
List<String[]> li = new ArrayList<String[]>();
li.add(header);
for (PoCsvUploadView group : csvDataList)
{
String[] arr = new String[31];
arr[0] = group.getCompany_cd();
.....
arr[30] = group.getVendor_type();
li.add(arr);
}
writer.writeAll(li);
} catch (Exception e) {
e.printStackTrace();
logger.error("Exception >> ", e);
throw new CustomGenericException(
"Error occured while loading report!!");
}finally{
writer.flush();
writer.close();
}
}
Now When I am click on the download button, the csv file is being generated at the specific location ie on fullPath variable. But that file is not downloading through the browser, instead of that browser is downloading some file named downloadPoCsv(which is exactly same as my #RequestMapping in my controller method), which is not desired. Can you guys provides some help on this. Thanx in advance.And yes I am using OpenCsv jar.
To be clear here the issue is spring MVC not openCSV because your problem description is that you are trying to download a file and it is downloading a file with a different name.
CodeJava has a pretty good example of a Spring MVC download. Give that a try.
Related
I want to upload the excel file to the Upload folder. But I have set the path properly in my controller, no idea how this error can be happen. Attached the controller code and error screen shot.
Controller code
[HttpPost]
public ActionResult UploadBatch(LogonUser logonUser, IEnumerable<HttpPostedFileBase> files)
{
JsonResultModel result = new JsonResultModel();
RegexUtilities util = new RegexUtilities();
try
{
foreach (HttpPostedFileBase file in files)
{
string fileName = Path.GetFileName(file.FileName);
string upDir = Path.Combine(Request.PhysicalApplicationPath, "Upload", DateTime.Now.ToString("HHmmss"));
string path = Path.Combine(upDir, fileName);
file.SaveAs(path);
}
}
catch (Exception ex)
{
result.Status = JsonResultStatus.Failed;
result.Message = ex.Message;
}
}
Error screenshot:
I'm using Xamarin.Forms and I am trying to convert an html string to a pdf file using EvoPdfConverter, but the problem is that when I try to do so, on the line htmlToPdfConverter.ConvertHtmlToFile(htmlData, "", myDir.ToString()); in the code snippet below, the app just freezes and does nothing, seems like it wants to connect to the given IP, but it can't, however I don't get any errors or exceptions! not even catch!! does anybody know what I should do to resolve this issue? and here is my code for this:
public void ConvertHtmlToPfd(string htmlData)
{
ServerSocket s = new ServerSocket(0);
HtmlToPdfConverter htmlToPdfConverter = new
HtmlToPdfConverter(GetLocalIPAddress(),(uint)s.LocalPort);
htmlToPdfConverter.TriggeringMode = TriggeringMode.Auto;
htmlToPdfConverter.PdfDocumentOptions.CompressCrossReference = true;
htmlToPdfConverter.PdfDocumentOptions.PdfCompressionLevel = PdfCompressionLevel.Best;
if (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.WriteExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions((Android.App.Activity)Android.App.Application.Context, new String[] { Manifest.Permission.WriteExternalStorage }, 1);
}
if (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.ReadExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions((Android.App.Activity)Android.App.Application.Context, new String[] { Manifest.Permission.ReadExternalStorage }, 1);
}
try
{
// create the HTML to PDF converter object
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
htmlToPdfConverter.LicenseKey = "4W9+bn19bn5ue2B+bn1/YH98YHd3d3c=";
htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
Java.IO.File myDir = new Java.IO.File(root + "/Reports");
try
{
myDir.Mkdir();
}
catch (Exception e)
{
string message = e.Message;
}
Java.IO.File file = new Java.IO.File(myDir, filename);
if (file.Exists()) file.Delete();
htmlToPdfConverter.ConvertHtmlToFile(htmlData, "", myDir.ToString());
}
catch (Exception ex)
{
string message = ex.Message;
}
}
Could you try to set a base URL to ConvertHtmlToFile call as the second parameter? You passed an empty string. That helps to resolve the relative URLs found in HTML to full URLs. The converter might have delays when trying to retrieve content from invalid resources URLs.
Suppose I have sample Upload file method like this in POStFile.aspx.
This method POST file (upload file) to http WEBDAV url.
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
log.Debug(string.Format("Uploading {0} to {1}", file, url));
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try {
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
} catch(Exception ex) {
log.Error("Error uploading file", ex);
if(wresp != null) {
wresp.Close();
wresp = null;
}
} finally {
wr = null;
}
}
From here
NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "TTR");
nvc.Add("btn-submit-photo", "Upload");
HttpUploadFile("http://your.server.com/upload",
#"C:\test\test.jpg", "file", "image/jpeg", nvc);
Question 1 : Shouldn't the url should be like "http://your.server.com/upload.aspx" instead of "http://your.server.com/upload"
If I give url like "http://your.server.com/upload" then i get 405 error method not found.
So it should point to any page.
Question 2 : How should I receive the post and save the file in upload.aspx.
Can the file directly uploaded to remote server without any receiving
page ?
This question was about "File transfer to WEBDAV http URL using or POST or PUT method"
Above is sample POST method.Similarly there can by PUT method which is little different from POST method.
Question 1 : Shouldn't the url should be like "http://your.server.com/upload.aspx" instead of "http://your.server.com/upload"
For novice man like me, main confusion is URL.It entirely depend upon "How WEBDAV server want to receive POST or PUT method ?"
I think for POST method ,there should be one receiving page which accept file and other parameters from POSTfile page and save the file to disk.
I don't know about .net code but WEB API has inbuilt feature which can parse data like "multipart/form-data; boundary=---------------------------8d60ff73d4553cc"
Below code is just sample code,
[HttpPost]
public async Task<FileUploadDetails> Post()
{
// file path
var fileuploadPath = HttpContext.Current.Server.MapPath("~/UploadedFiles");
////
var multiFormDataStreamProvider = new MultiFileUploadProvider(fileuploadPath);
// Read the MIME multipart asynchronously
await Request.Content.ReadAsMultipartAsync(multiFormDataStreamProvider);
string uploadingFileName = multiFormDataStreamProvider
.FileData.Select(x => x.LocalFileName).FirstOrDefault();
// Files
//
foreach (MultipartFileData file in multiFormDataStreamProvider.FileData)
{
Debug.WriteLine(file.Headers.ContentDisposition.FileName);
Debug.WriteLine("File path: " + file.LocalFileName);
}
// Form data
//
foreach (var key in multiFormDataStreamProvider.FormData.AllKeys)
{
foreach (var val in multiFormDataStreamProvider.FormData.GetValues(key))
{
Debug.WriteLine(string.Format("{0}: {1}", key, val));
}
}
//Create response
return new FileUploadDetails
{
FilePath = uploadingFileName,
FileName = Path.GetFileName(uploadingFileName),
FileLength = new FileInfo(uploadingFileName).Length,
FileCreatedTime = DateTime.Now.ToLongDateString()
};
return null;
}
So url in POSTFile.aspx page should point to API method in this case,
"http://your.server.com/api/fileUpload"
where fileUpload is api controller name.
If you are using HTTP PUT method then
i) you want to receive it in pro grammatically handle it.Write PUT method similar to POST method in api class.
ii) you want to directly save the file to folder using PUT method.
so URL in this case can be,
"http://your.server.com/Imagefolder"
Yes this can be done with extra IIS setting.
Create virtual directory in Target folder,beside few other thing.
I have a Spring MVC controller that accepts a MultipartFile, which will be a zip file. The problem is I can't seem to go from that to a ZipInputStream or ZipFile, so that I can go through the entries. It either closes the stream prematurely, produces an empty file, or as in the case below, zipInputStream.getNextEntry() returning null.
This is my MVC controller:
#RequestMapping(value = "/content/general-import", method = RequestMethod.POST)
public ModelAndView handleGeneralUpload(
#RequestParam("file") MultipartFile file) throws IOException {
// hard code the signature for the moment
String signature = "RETAILER_GROUP:*|CHANNEL:*|LOCALE:de-AT|INDUSTRY:5499";
LOG.info("Processing file archive: {} with signature: {}.", file.getName(), signature);
ModelAndView mav = new ModelAndView();
mav.setViewName("contentUpload");
LOG.debug("File={} is empty={}.", file.getName(), file.isEmpty());
if (!file.isEmpty()) {
processFileZipEntry(file, signature);
mav.addObject("form", UploadViewModel.make("/content/general-import", "Updated content with file"));
return mav;
} else {
mav.addObject("form", UploadViewModel.make("/content/general-import", "Could not update content with file"));
return mav;
}
}
It delegates to the following method for processing:
protected void processFileZipEntry(MultipartFile file, String signature) throws IOException {
byte[] bytes = file.getBytes();
LOG.debug("Processing archive with bytes={}.", file.getBytes().length);
ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes));
LOG.debug("Processing archive with size={}.", file.getSize());
ZipEntry entry = null;
while ((entry = zis.getNextEntry()) != null) {
LOG.debug("Processing file={} is directory?={}.", entry.getName(), entry.isDirectory());
// process each file, based on what it is and whether its a directory etc.
if (!entry.isDirectory()) {
// if the entry is a file, extract it
LOG.debug("Processing entry: {}",entry.getName());
int length = (int) entry.getSize();
Content contentToSave = null;
if(entry.getName().contains("gif")) {
contentToSave = Content.makeImage(entry.getName(), Content.GIF, signature, getBytesFrom(zis, "gif"));
} else if (entry.getName().contains("png")) {
contentToSave = Content.makeImage(entry.getName(), Content.PNG, signature, getBytesFrom(zis, "png"));
} else if (entry.getName().contains("jpeg")) {
contentToSave = Content.makeImage(entry.getName(), Content.JPEG, signature, getBytesFrom(zis, "jpeg"));
} else if (entry.getName().contains("json")) {
contentToSave = Content.makeFile(entry.getName(), Content.JSON, signature, getStringFrom(zis, length));
} else if (entry.getName().contains("js")) {
contentToSave = Content.makeFile(entry.getName(), Content.JS, signature, getStringFrom(zis, length));
} else if (entry.getName().contains("css")) {
contentToSave = Content.makeFile(entry.getName(), Content.CSS, signature, getStringFrom(zis, length));
}
Content contentAleadyThere = contentService.fetch(entry.getName());
if(contentAleadyThere != null) {
LOG.warn("Replacing file: {} with uploaded version.", contentToSave.getName());
}
contentService.put(contentToSave);
LOG.info("Persisted file: {} from uploaded version.", contentToSave.getName());
}
}
}
Basically, in this permutation, the file bytes are there, but there are no entries (zis.getNextEntry() does not exist. I can see that the zip file contains files, and the byte[] has about 3MB worth of stuff, so something must be going wrong with the streaming. Does anyone have a recipe for going from MultipartFile to ZipFile or ZipInputStream?
EDIT
To give you more information, I have a test harnass around this code, by using a MockMvc
#Test
public void testProcessingGeneralUpload() throws Exception {
Resource template = wac.getResource("classpath:lc_content/content.zip");
System.out.println("template content length: " + template.contentLength());
System.out.println("template path: " + template.getFile().getPath());
System.out.println("template filename: " + template.getFilename());
MockMultipartFile firstFile = new MockMultipartFile(
"file", "content.zip", MediaType.APPLICATION_OCTET_STREAM_VALUE, extractFile(template.getFile()));
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.fileUpload("/content/general-import")
.file(firstFile))
.andExpect(status().isOk())
.andExpect(view().name("contentUpload"))
.andExpect(model().attributeExists("form")).andReturn();
// processing assertions
ModelMap modelMap = mvcResult.getModelAndView().getModelMap();
Object object = modelMap.get("form");
assertThat(object, is(not(nullValue())));
assertThat(object, is(instanceOf(UploadViewModel.class)));
UploadViewModel addModel = (UploadViewModel) object;
assertThat(addModel.getMessage(), is(notNullValue()));
assertThat(addModel.getPostUrl(), is(notNullValue()));
assertThat(addModel.getPostUrl(), is("/content/general-import"));
assertThat(addModel.getMessage(), is("Updated content with file"));
// persistence assertions
assertThat(contentDao.findByName("/content/control/basket-manager.js"), is(notNullValue()) );
}
The extractFile method is as follows:
private byte[] extractFile(File zipFile) throws IOException {
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFile));
System.out.println("length of file: " + zipFile.length());
byte[] output = null;
try {
byte[] data = new byte[(int)zipFile.length()];
zipIn.read(data);
zipIn.close();
output = data;
} catch (IOException e) {
e.printStackTrace();
}
return output;
}
The length of bytes it produces is 3617817, which is the size I expect, and this is fed into the controller method at the top of this question.
I have continued working the problem. The size of the file is correct, it is a zipped file (it unpacks via the OS perfectly), and yet no ZipEntry enumeration.
I would for starters rewrite some of the code instead of doing things in memory with additional byte[].
You are using Spring's Resource class so why not simply use the getInputStream() method to construct the MockMultipartFile as you want to upload that file.
Resource template = wac.getResource("classpath:lc_content/content.zip");
MockMultipartFile firstFile = new MockMultipartFile(
"file", "content.zip", MediaType.APPLICATION_OCTET_STREAM_VALUE, template.getInputStream());
The same for your upload processing code the ZipInputStream can also be constructed on another InputStream which is also provided by the MultipartFile interface.
protected void processFileZipEntry(MultipartFile file, String signature) throws IOException {
LOG.debug("Processing archive with size={}.", file.getSize());
ZipInputStream zis = new ZipInputStream(file.getInputStream());
Wouldn't be the first time that jugling around with byte[] gives a problem. I also vaguely recall some issues with ZipInputStream which lead us to use ZipFile but for this you will first have to store the file in a temp directoy using the transferTo method on MultipartFile.
File tempFile = File.createTempFile("upload", null);
file.transferTo(tempFile);
ZipFile zipFile = new ZipFle(tempFile);
// Proces Zip
tempFile.delete();
I'm trying to use valums ajax uploader. http://valums.com/ajax-upload/
I have the following on my page:
var button = $('#fileUpload')[0];
var uploader = new qq.FileUploader({
element: button,
allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'],
sizeLimit: 2147483647, // max size
action: '/Admin/Home/Upload',
multiple: false
});
it does post to my controller but qqfile is always null. I tried these:
public ActionResult Upload(HttpPostedFile qqfile)
AND
HttpPostedFileBase file = Request.Files["file"];
without any luck.
I found an example for ruby on rails but not sure how to implement it in MVC
http://www.jigsawboys.com/2010/10/06/ruby-on-rails-ajax-file-upload-with-valum/
In firebug i see this:
http://localhost:61143/Admin/Home/Upload?qqfile=2glonglonglongname+-+Copy.gif
I figured it out. this works in IE and Mozilla.
[HttpPost]
public ActionResult FileUpload(string qqfile)
{
var path = #"C:\\Temp\\100\\";
var file = string.Empty;
try
{
var stream = Request.InputStream;
if (String.IsNullOrEmpty(Request["qqfile"]))
{
// IE
HttpPostedFileBase postedFile = Request.Files[0];
stream = postedFile.InputStream;
file = Path.Combine(path, System.IO.Path.GetFileName(Request.Files[0].FileName));
}
else
{
//Webkit, Mozilla
file = Path.Combine(path, qqfile);
}
var buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
System.IO.File.WriteAllBytes(file, buffer);
}
catch (Exception ex)
{
return Json(new { success = false, message = ex.Message }, "application/json");
}
return Json(new { success = true }, "text/html");
}
This component is sending an application/octet-stream instead of multipart/form-data which is what the default model binder can work with. So you cannot expect Request.Files to have any value with such a request.
You will need to manually read the request stream:
public ActionResult Upload(string qqfile)
{
var stream = Request.InputStream;
var buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
var path = Server.MapPath("~/App_Data");
var file = Path.Combine(path, qqfile);
File.WriteAllBytes(file, buffer);
// TODO: Return whatever the upload control expects as response
}
IE uploads using multipart-mime. Other browsers use Octet-Stream.
I wrote an upload handler to work with Valums Ajax Uploader that works with both MVC & Webforms & both upload methods. I'd be happy to share with you if you wanted. It closely follows the the PHP handler.
My controller to handle the upload looks like this:
public class UploadController : Controller
{
private IUploadService _Service;
public UploadController()
: this(null)
{
}
public UploadController(IUploadService service)
{
_Service = service ?? new UploadService();
}
public ActionResult File()
{
return Content(_Service.Upload().ToString());
}
The UploadService looks this:
public class UploadService : IUploadService
{
private readonly qq.FileUploader _Uploader;
public UploadService()
: this(null)
{ }
public UploadService(IAccountService accountservice)
{
_Uploader = new qq.FileUploader();
}
public UploadResult Upload()
{
qq.UploadResult result = _Uploader.HandleUpload();
if (!result.Success)
return new UploadResult(result.Error);
.... code .....
return new UploadResult((Guid)cmd.Parameters["#id"].Value);
}
catch (Exception ex)
{
return new UploadResult(System.Web.HttpUtility.HtmlEncode(ex.Message));
}
finally
{
............code.........
}
}
...............code ............
You should try:
Stream inputStream = (context.Request.Files.Count > 0) ? context.Request.Files[0].InputStream : context.Request.InputStream;
I am developing in ASP.Net 4.0 but we don't have MVC architecture. I had same issue few days back. But, I figured it out and here is my solution.
//For IE Browser
HttpPostedFile selectedfile = Request.Files[0];
System.Drawing.Bitmap obj = new System.Drawing.Bitmap(selectedfile.InputStream);
//For Non IE Browser
System.Drawing.Bitmap obj = new System.Drawing.Bitmap(Request.InputStream);
Now, you can use obj for further operation.