smartgwt spring servlet and uploading files - rest

I've seen this question here before, but none of the solutions work for me.
I have a SmartGWT app with Spring MVC. This all works great, and I have working RESTful web-services.
I have a form to upload not only the file, but also some meta data as well.
There is an associated DataSource with this form:
private final String DEFAULT_FILE_UPLOAD_SERVICE_PATH = "upload";
private final String TARGET = "uploadTarget";
public FileUploadForm()
{
setEncoding(Encoding.MULTIPART);
setMethod(FormMethod.POST);
setAutoFetchData(false);
setDataSource(fileUploadDS);
setTitleOrientation(TitleOrientation.TOP);
setNumCols(1);
setColWidths("*");
uploadFileIdItem.setRequired(true);
uploadFileIdItem.setDefaultValue(0);
uploadFileIdItem.setVisible(false);
uploadFileIdItem.setShowTitle(false);
// ==========================================================================
fileUploadTypeSelectItem.setShowTitle(false);
fileUploadTypeSelectItem.setName(Constants.FILE_UPLOAD_UPLOADTYPE);
fileUploadTypeSelectItem.setPickListWidth(TEXT_SIZE);
fileUploadTypeSelectItem.setTitle(Constants.TITLE_FILE_UPLOAD_UPLOADTYPE);
fileUploadTypeSelectItem.setOptionDataSource(fileUploadTypeDS);
fileUploadTypeSelectItem.setRequired(true);
fileUploadTypeSelectItem.setDisplayField(Constants.FILE_UPLOAD_UPLOADTYPE_NAME);
fileUploadTypeSelectItem.setValueField(Constants.FILE_UPLOAD_UPLOADTYPE_ID);
fileUploadTypeSelectItem.setDataPath("fileUploadType/fileUploadTypeId");
// ==========================================================================
setAction(GWT.getHostPageBaseURL() + "rest/" + DEFAULT_FILE_UPLOAD_SERVICE_PATH);
ButtonItem uploadButton = new ButtonItem("Upload");
uploadButton.addClickHandler(new com.smartgwt.client.widgets.form.fields.events.ClickHandler()
{
#Override
public void onClick(com.smartgwt.client.widgets.form.fields.events.ClickEvent event)
{
submitForm();
}
});
FileItem uploadItem = new FileItem(Constants.FILENAME);
uploadItem.setTitle(Constants.FILENAME);
setFields(uploadFileIdItem, fileUploadTypeSelectItem, uploadItem, uploadButton);
}
So, I don't know if I need to use:
setAction(GWT.getHostPageBaseURL() + "rest/" + DEFAULT_FILE_UPLOAD_SERVICE_PATH);
or
setAction(GWT.getHostPageBaseURL() + DEFAULT_FILE_UPLOAD_SERVICE_PATH);
or
setAction(GWT.getHostPageBaseURL() + DEFAULT_FILE_UPLOAD_SERVICE_PATH);
None of these seem to work, I submit my data to upload the filename, and I constantly get the HTTP 404 error.
I did not define anything extra special in the web.xml file for servlets.
Instead, the springmvc-servlet contains:
<context:component-scan base-package="com.myself.products.app.server.controller" />
And the servlet is actually defined like:
#SuppressWarnings("serial")
#Controller
#RequestMapping("/upload")
public class FileUploadServlet extends HttpServlet
{
private final Logger logger = LoggerFactory.getLogger(FileUploadServlet.class);
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
this.process(request, response);
}
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
this.process(request, response);
}
private void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// check that we have a file upload request
if (ServletFileUpload.isMultipartContent(request))
{
processFiles(request, response);
}
}
private File tmpDir;
private static final String DESTINATION_DIR_PATH = "/files/upload";
private File destinationDir;
public void init(ServletConfig config) throws ServletException
{
super.init(config);
tmpDir = new File(((File) getServletContext().getAttribute("javax.servlet.context.tempdir")).toString());
if (!tmpDir.isDirectory())
{
throw new ServletException(tmpDir.toString() + " is not a directory");
}
logger.debug("tmpDir: " + tmpDir.toString());
String realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH);
destinationDir = new File(realPath);
if (!destinationDir.isDirectory())
{
throw new ServletException(DESTINATION_DIR_PATH + " is not a directory");
}
}
private void processFiles(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException
{
// create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// set the size threshold, above which content will be stored on disk
factory.setSizeThreshold(1 * 1024 * 1024); // 1 MB
// set the temporary directory (this is where files that exceed the threshold will be stored)
factory.setRepository(tmpDir);
// create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
try
{
// parse the request
List<?> items = upload.parseRequest(request);
// process the uploaded items
Iterator<?> itr = items.iterator();
while (itr.hasNext())
{
FileItem item = (FileItem) itr.next();
// write the uploaded file to the application's file staging area
File file = new File(destinationDir, item.getName());
item.write(file);
}
}
catch (FileUploadException e)
{
logger.error("Error encountered while parsing the request", e);
}
catch (Exception e)
{
logger.error("Error encountered while uploading file", e);
}
}
You've seen this code before along this web-site, and several others.
I'd like to submit the file, AND data if possible, but if not, then how can I submit the form, and then metadata for it?
Any help would be much appreciated.

Simple File Upload GWT Example:
Available here:
http://www.gwtproject.org/javadoc/latest/com/google/gwt/user/client/ui/FileUpload.html
For sending Metadata along with request, need to set the hidden field to panel:
import com.google.gwt.user.client.ui.Hidden;
Hidden hidden = new Hidden();
hidden.setName("json");
hidden.setVisible(false);
hidden.setValue("simpleMetadata:testData");
panel.add(hidden);

I will suggest you to seperate saving metadata from uploding a file and have 2 forms. This is what I'm doing and it is working for me:
uploadForm.setAction(GWT.getHostPageBaseURL() + "importServiceName");
uploadForm.setEncoding(Encoding.MULTIPART);
uploadForm.setTarget(TARGET);
uploadForm.setMethod(FormMethod.POST);
fileItem = new UploadItem("file");
fileItem.setTitle("File");
fileItem.setWidth(300);
NamedFrame frame = new NamedFrame(TARGET);
frame.setWidth("1");
frame.setHeight("1");
frame.setVisible(false);
uploadForm.setItems(fileItem);
I'm using NamedFrame to be able to fetch servlet response in gwt code, but this is different story. I'm defining servler manually in web.xml

Related

Spring boot rest service to download a zip file which contains multiple file

I am able to download a single file but how I can download a zip file which contain multiple files.
Below is the code to download a single file but I have multiples files to download. Any help would greatly appreciated as I am stuck on this for last 2 days.
#GET
#Path("/download/{fname}/{ext}")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(#PathParam("fname") String fileName,#PathParam("ext") String fileExt){
File file = new File("C:/temp/"+fileName+"."+fileExt);
ResponseBuilder rb = Response.ok(file);
rb.header("Content-Disposition", "attachment; filename=" + file.getName());
Response response = rb.build();
return response;
}
Here is my working code I have used response.getOuptStream()
#RestController
public class DownloadFileController {
#Autowired
DownloadService service;
#GetMapping("/downloadZip")
public void downloadFile(HttpServletResponse response) {
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=download.zip");
response.setStatus(HttpServletResponse.SC_OK);
List<String> fileNames = service.getFileName();
System.out.println("############# file size ###########" + fileNames.size());
try (ZipOutputStream zippedOut = new ZipOutputStream(response.getOutputStream())) {
for (String file : fileNames) {
FileSystemResource resource = new FileSystemResource(file);
ZipEntry e = new ZipEntry(resource.getFilename());
// Configure the zip entry, the properties of the file
e.setSize(resource.contentLength());
e.setTime(System.currentTimeMillis());
// etc.
zippedOut.putNextEntry(e);
// And the content of the resource:
StreamUtils.copy(resource.getInputStream(), zippedOut);
zippedOut.closeEntry();
}
zippedOut.finish();
} catch (Exception e) {
// Exception handling goes here
}
}
}
Service Class:-
public class DownloadServiceImpl implements DownloadService {
#Autowired
DownloadServiceDao repo;
#Override
public List<String> getFileName() {
String[] fileName = { "C:\\neon\\FileTest\\File1.xlsx", "C:\\neon\\FileTest\\File2.xlsx", "C:\\neon\\FileTest\\File3.xlsx" };
List<String> fileList = new ArrayList<>(Arrays.asList(fileName));
return fileList;
}
}
Use these Spring MVC provided abstractions to avoid loading of whole file in memory.
org.springframework.core.io.Resource & org.springframework.core.io.InputStreamSource
This way, your underlying implementation can change without changing controller interface & also your downloads would be streamed byte by byte.
See accepted answer here which is basically using org.springframework.core.io.FileSystemResource to create a Resource and there is a logic to create zip file on the fly too.
That above answer has return type as void, while you should directly return a Resource or ResponseEntity<Resource> .
As demonstrated in this answer, loop around your actual files and put in zip stream. Have a look at produces and content-type headers.
Combine these two answers to get what you are trying to achieve.
public void downloadSupportBundle(HttpServletResponse response){
File file = new File("supportbundle.tar.gz");
Path path = Paths.get(file.getAbsolutePath());
logger.debug("__path {} - absolute Path{}", path.getFileName(),
path.getRoot().toAbsolutePath());
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=supportbundle.tar.gz");
response.setStatus(HttpServletResponse.SC_OK);
System.out.println("############# file name ###########" + file.getName());
try (ZipOutputStream zippedOut = new ZipOutputStream(response.getOutputStream())) {
FileSystemResource resource = new FileSystemResource(file);
ZipEntry e = new ZipEntry(resource.getFilename());
e.setSize(resource.contentLength());
e.setTime(System.currentTimeMillis());
zippedOut.putNextEntry(e);
StreamUtils.copy(resource.getInputStream(), zippedOut);
zippedOut.closeEntry();
zippedOut.finish();
} catch (Exception e) {
}
}

Twitter object is always null I have taken example from twitter4j

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
TwitterFactory twitterFac = new TwitterFactory();
Twitter twitter = twitterFac.getInstance();
twitter.setOAuthConsumer("key", "secret");
request.getSession().setAttribute("twitter", twitter);
try
{
RequestToken requestToken = twitter.getOAuthRequestToken("http://local.your-domain.com:8080/sign-in-with-twitter/callback");
request.getSession().setAttribute("requestToken", requestToken);
System.out.println(requestToken.getAuthenticationURL());
response.sendRedirect(requestToken.getAuthenticationURL());
} catch (TwitterException e)
{
throw new ServletException(e);
}
}
}
****Then the twitter page redirects to a page of my application (CallbackServlet). All this is performed correctly.****
Then the CallbackServlet has the following doGet method:
public class CallbackServlet extends HttpServlet {
private static final long serialVersionUID = 1657390011452788111L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Twitter twitter = (Twitter) request.getSession().getAttribute("twitter");
RequestToken requestToken = (RequestToken) request.getSession().getAttribute("oauth_token");
String verifier = request.getParameter("oauth_verifier");
try {
twitter.getOAuthAccessToken(requestToken, verifier);
request.getSession().removeAttribute("requestToken");
} catch (TwitterException e) {
throw new ServletException(e);
}
response.sendRedirect(request.getContextPath() + "/");
}
}
=============================
The CallbackServlet tries to get the twitter and requestToken saved in the LoginServlet (using the method getSession().getAttribute()). This is where the problem is: the twitter object is always null!
plz sort it out

how to get file content from file using gwtupload

i am using GWTUpload to upload a file.
i am getting the server info, file name, content type etc.. in onFinishHandler, but there's no option to get the file content from server to client.
Note : am trying to upload XML File and EXCEL File
i am using GWT 2.4, GXT 3.0.1, GWTUpload 0.6.6
here's the sample code
Client Code - OnFinishHandler
u.addOnFinishUploadHandler(new OnFinishUploaderHandler() {
#Override
public void onFinish(IUploader uploader) {
if (uploader.getStatus() == Status.SUCCESS) {
System.err.println(uploader.getServerResponse());
UploadedInfo info = uploader.getServerInfo();
System.out.println("File name " + info.name);
System.out.println("File content-type " + info.ctype);
System.out.println("File size " + info.size);
System.out.println("Server message " + info.message);
}
}
});
Servlet Code
public class GWTFileUploadServlet extends UploadAction {
private static final long serialVersionUID = -6742854283091447922L;
String fileContent;
File uploadedFile;
#Override
public String executeAction(HttpServletRequest request,
List<FileItem> sessionFiles) throws UploadActionException {
String response = "";
int cont = 0;
for (FileItem item : sessionFiles) {
if (false == item.isFormField()) {
cont++;
try {
File file = File.createTempFile("upload-", ".bin");
item.write(file);
uploadedFile = file;
fileContent = item.getContentType();
response += "File saved as " + file.getAbsolutePath();
} catch (Exception e) {
throw new UploadActionException(e.getMessage());
}
}
}
removeSessionFileItems(request);
return response;
}
#Override
public void getUploadedFile(HttpServletRequest request,
HttpServletResponse response) throws IOException {
if (fileContent != null && !fileContent.isEmpty()) {
response.setContentType(fileContent);
FileInputStream is = new FileInputStream(uploadedFile);
copyFromInputStreamToOutputStream(is, response.getOutputStream());
} else {
renderXmlResponse(request, response, XML_ERROR_ITEM_NOT_FOUND);
}
}
}
please help me....
You can read the file you have created in the filesystem when you called item.write(...), but it is better if you get an InputStream from the FileItem you received and write its content anywhere. For instance if the content is a String you can use a StringWritter to get it:
InputStream inputStream = item.getInputStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer);
String theContentString = writer.toString();
[EDITED]
To get the content of the file in client side, so you have to retrieve it from the server using any method:
As as a customized message in your gwtupload servlet if the content of the file is ascii: use return String of executeAction.
Do a RequestBuilder call to the servlet to get the file using the uploader url value.
Use any GWT ajax mechanism like RPC.
In modern browsers you can get the content of a file in client side without sending it to server side. Take a look to lib-gwt-file
In your code You can just use
byte[] file ;
file = item.get();
And You will get all the file content in an encoded format in the "file" variable .

Read form file and send its contents to the clinet in GWT

I need to read form TXT file on the server side and send its contents to the client side to print in a label or any thing, i need to know where i place the TXT file is it on the server package or in WAR and how to code it?? thanks
It doens't really matter where you place the file. It must be on the server and a php script must be able to open the file. You can ready the text file the following way with php.
Then make a http request with GWT to that file.
Read the file:
<?php
// get contents of a file into a string
$filename = "/usr/local/something.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
echo $contents;
?>
Make http request:
public class GetExample implements EntryPoint {
public static final int STATUS_CODE_OK = 200;
public static void doGet(String url) {
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
Request response = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Code omitted for clarity
}
public void onResponseReceived(Request request, Response response) {
String content = response.getText();
}
});
} catch (RequestException e) {
// Code omitted for clarity
}
}
public void onModuleLoad() {
doGet("/");
}
}

save an uploaded file with GWT

I am using org.apache.commons.fileupload to upload.
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
GWT.log("is multipart? " + Boolean.toString(isMultipart), null);
ServletFileUpload upload = new ServletFileUpload();
try{
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream() ;
/**
* Save th uploaded file
*/
}
}
catch(Exception e){
e.printStackTrace();
}
}
How can I save the uploaded file?
This looks like server-side code, which (aside from GWT-RPC servlets) is not specific to GWT at all. That GWT.log() is unnecessary -- replace it with a regular logging call, and handle the upload as you normally would in non-GWT code, since that's what it is.
Here is a helpful example of using apache's fileupload to get you started.
I think this can help you.
if (!item.isFormField()) {
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
File saveTo = new File("/file_uploads/" + fileName);
try {
item.write(saveTo);
...
}
catch (Exception e){
...
}
Keep in mind that uploaded file may already be automatically saved by org.apache.commons.fileupload
You can set size threshold for file to be saved on disk or loaded in memory using
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Set factory constraints
factory.setSizeThreshold(yourMaxMemorySize);
factory.setRepository(yourTempDirectory);
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Set overall request size constraint
upload.setSizeMax(yourMaxRequestSize);
// Parse the request
List /* FileItem */ items = upload.parseRequest(request);
Everything you need to know about org.apache.commons.fileupload is here: Using FileUpload