I am trying to upload file using QBCustomObjectFiles ,uploading starts to show progress in log cat ,but with file field is null and response throws error like this '{"errors":["The resource wasn't found"]}'
I checked My Note Class on Quickblox admin panel,everything seems OK.Also I checked the file (field in method parameter) and it is not null as showing in log cat
public void uploadNote(Note note, File file,
QBEntityCallback<QBCustomObjectFileField> callback, QBProgressCallback
progressCallback) {
QBCustomObject customObject = new QBCustomObject();
customObject.setClassName(Note.Contract.CLASS_NAME_NOTE);
customObject.put(Note.Contract.COURSE_ID,note.getCourseId());
customObject.put(Note.Contract.CATEGORY_ID,note.getCategoryId());
customObject.put(Note.Contract.DESCRIPTION,note.getDescription());
customObject.put(Note.Contract.TOPIC,note.getTopic());
QBCustomObjectsFiles.uploadFile(file, customObject, "noteFile", progressCallback).performAsync(callback);
}
This is my log cat :
REQUEST
POST https://api.quickblox.com/data/Note/null/file.json
HEADERS
QuickBlox-REST-API-Version=0.1.1
QB-SDK=Android 3.9.1
QB-Token=011a2bc55be67185d4d045d8b2d31
PARAMETERS
field_name=noteFile
INLINE
POST https://api.quickblox.com/data/Note/null/file.json?field_name=noteFile
and this is response
'{"errors":["The resource wasn't found"]}'
The Uploading starts and shows progress ,but after progress 100 it throws above error.
You should use QBContent instead of QBCustomObjectsFiles. Example:
QBContent.uploadFileTask(file, isPublic, tags, new QBProgressCallback() {
#Override
public void onProgressUpdate(int progressValue) {
//some code for progress
}
}).performAsync(new QBEntityCallback<QBFile>() {
#Override
public void onSuccess(QBFile qbFile, Bundle params) {
//some code for success upload
}
#Override
public void onError(QBResponseException responseException) {
//some code for error upload
}
});
I've successfully read a pdf from the project and displayed in a WebView. What I want to do is to get the pdf file path from my project and check if it exists to display it, and if not, to give it another URI to open with. Anyone knows how I can get the path of the pdf and it works for both Android and iOS.
Here is my C# code:
string internalstorageurl = string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode("Conctionprofile.pdf"));
public pdfviewer ()
{
InitializeComponent ();
PDFReading();
}
private void PDFReading()
{
pdfwebview.Uri = internalstorageurl;
}
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AppXamarin.CustomRenders"
x:Class="AppXamarin.Pages.pdfviewer"
Padding="0,20,0,0">
<ContentPage.Content>
<local:CustomWebView x:Name="pdfwebview" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
</ContentPage.Content>
</ContentPage>
I'm checking if the file exist in my project with this code:
[assembly: Dependency(typeof(GetPdfFilePath_Android))]
namespace AppXamarin.Droid.CustomRender
{
public class GetPdfFilePath_Android : Java.Lang.Object, IGetPdfFilePath
{
public string filePath(string fileName)
{
string internalstorageurl = string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode(fileName));
if (File.Exists(internalstorageurl))
return internalstorageurl;
else
return "not found";
}
}
}
The if statement is always false
You can use dependencyService to get pdf file path from both iOS and Android app.
The interface:
public interface IGetPdfFilePath
{
string filePath(string fileName);
}
Get the file path in Xamarin.forms:
string pdfPath = DependencyService.Get<IGetPdfFilePath>().filePath("myPdf.pdf");
Console.WriteLine(pdfPath);
In iOS, the path is depending on where you store the file:
[assembly: Dependency (typeof (GetPdfFilePath_iOS))]
namespace UsingDependencyService.iOS
{
public class GetPdfFilePath_iOS : IGetPdfFilePath
{
public GetPdfFilePath_iOS ()
{
}
public string filePath(string fileName)
{
// 1. if your store your pdf in DocumentDirectory
//string directories = NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.All)[0];
//string pathBundle = directories + "/" + fileName;
////bool fileExists = NSFileManager.DefaultManager.FileExists(pathBundle);
//return pathBundle;
//2.pdf file in your project
string pathBundle = Path.Combine(NSBundle.MainBundle.ResourcePath, fileName);
return pathBundle;
}
}
}
In Android:
[assembly: Dependency(typeof(GetPdfFilePath_Android))]
namespace UsingDependencyService.Android
{
public class GetPdfFilePath_Android : Java.Lang.Object, IGetPdfFilePath
{
public string filePath(string fileName)
{
string internalstorageurl = string.Format("file:///android_asset/Content/{0}", WebUtility.UrlEncode(fileName));
return internalstorageurl;
}
}
}
Update:
Add this line: [assembly: Dependency(typeof(GetPdfFilePath_Android))] to your Android class. GetPdfFilePath_Android here is your class name.
Another way is to create a custom renderer of your webview, you can have a look at this project.
Update to check file:, I add this method in the Android to check if the file exist inside Assets/Content.
public bool fileExist (string fileName) {
AssetManager assets = MainActivity.Instance.Assets;
string[] names = assets.List("Content");
for (int i = 0; i < names.Length; i++)
{
if (names[i] == fileName)
{
return true;
}
}
return false;
}
Note: You have to change the build action of pdf file to AndroidAsset if you can't find the file inside Assets.
So in this code what I want is a random SQL query from the outside that will be loaded into a property file. As of now i've got the property file with a query in it to test this. So i would like some data out, with a headline and all the data beneath. Basically just the data to start with though, as this test should do. But I get the error message that i've linked below. I can't for the life of me figure out where my problem is. Help please! :)
I've got the following code;
DataHandler class.
public class DataHandler{
DataService dataService = new DataService();
public String getPropertyValue() throws IOException {
Properties prop = new Properties();
String propFileName = "randomSqlQuery.properties";
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
prop.load(inputStream);
if (inputStream == null) {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
String result = prop.getProperty("sqlQuery");
return result;
}
public Data getKeysAndValues() throws IOException {
String query = getPropertyValue();
List<List<Object>> randomSqlQuery = dataService.getRandomSqlQuery(query);
List<List<Object>> recordList = new ArrayList<>();
List<String> headline = new ArrayList();
if (randomSqlQuery != null && randomSqlQuery.size() > 0) {
{
List<Object> record = randomSqlQuery.get(0);
getHeadlines(record, headline);
}
for (int i = 1; i < randomSqlQuery.size(); i++) {
List<Object> singleRecord = randomSqlQuery.get(i);
recordList.add(singleRecord);
System.out.println(recordList);
}
}
return new DataImpl(headline, recordList);
}
private void getHeadlines(List<Object> record, List<String> headline) {
for (Object headlineName : record) {
headline.add((String) headlineName);
System.out.println(headlineName);
}
}
}
DataMapper class
public interface DataMapper {
public List<List<Object>> getRandomSqlQuery(#Param("query") String query);
}
DataMapper XML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="nd.mappers.DataMapper">
<select id="getRandomSqlQuery" resultType="java.util.List">
${query}
</select>
</mapper>
DataImpl class, which has an interface connected to it
public class DataImpl implements Serializable, Data {
private final List<String> headers;
private final List<List<Object>> records;
public DataImpl(List<String> headers, List<List<Object>> records) {
this.headers = Collections.unmodifiableList(headers);
this.records = Collections.unmodifiableList(records);
}
#Override
public List<String> getHeaders() {
return this.headers;
}
#Override
public List<List<Object>> getRecords() {
return this.records;
}
}
And a DataService class
public class DataService implements DataMapper {
#Override
public List<List<Object>> getRandomSqlQuery(String query) {
SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession();
try {
DataMapper dataMapper = sqlSession.getMapper(DataMapper.class);
return dataMapper.getRandomSqlQuery(query);
} finally {
sqlSession.close();
}
}
}
Finally the test
//dataHandler instantiated in top
#Test
public void getKeysAndValues() throws IOException {
dataHandler.getKeysAndValues();
}
And here is my error!
### Error querying database. Cause: java.lang.UnsupportedOperationException
### The error may exist in nd/mappers/DataMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT * FROM PERSON ### Cause: java.lang.UnsupportedOperationException
org.apache.ibatis.exceptions.PersistenceException
### Error querying database. Cause: java.lang.UnsupportedOperationException
### The error may exist in nd/mappers/DataMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT * FROM PERSON
### Cause: java.lang.UnsupportedOperationException
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:26)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:111)
No idea what to do. The SQL is coming from the property file. Sorry for massive text.
I just resolved the same error message. The problem lies here:
<select id="getRandomSqlQuery" resultType="Person">
${query}
</select>
The result type should not be a collection but a type that the
collection contains. In your case it should be some Person
POJO. This type then must be defined in the (say mybatis-config.xml) configuration
file:
<typeAliases>
<typeAlias alias="Person" type="com.example.bean.Book"/>
</typeAliases>
Also, you would want to check for null here:
try {
DataMapper dataMapper = qlSession.getMapper(DataMapper.class);
return dataMapper.getRandomSqlQuery(query);
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
I have a simple bean, like that:
package models;
import play.data.validation.Constraints;
public class Upload
{
#Constraints.Required
#Constraints.MinLength(4)
#Constraints.MaxLength(40)
public String name;
#Constraints.Required
public String inputFile;
}
and form, like that:
#form(action = routes.Application.submit(), 'enctype -> "multipart/form-data") {
#inputText(
uploadForm("name"),
'_label -> "Name"
)
#inputFile(
uploadForm("inputFile"),
'_label -> "Queries"
)
}
What is the best way to validate inputFile?
Is it possible do to that with annotations?
#Required constraint does not work at all.
I want it to be selected + add some limitation on size.
make your form like:
<input type="file" name="inputFile">
In you submit method add this:
// from official documentation
public static Result submit() {
MultipartFormData body = request().body().asMultipartFormData();
FilePart file = body.getFile("inputFile");
if (inputFile != null) {
String fileName = picture.getFilename();
String contentType = picture.getContentType();
File file = picture.getFile();
// method the check size
if(!validateFileSize){
return redirect(routes.Application.index()); // error in file size
}
return ok("File uploaded");
} else {
// here comes the validation
flash("error", "Missing file");
return redirect(routes.Application.index());
}
}
Something like the following, maybe?
MultipartFormData body = request().body().asMultipartFormData();
if (!body.getFiles().isEmpty()) {
// do your work
}
I'm having two problems when trying to configure the Struts 2 File Upload Interceptor in my application. I want to change the parameter maximumSize (the default value is 2 MB, I need it to be 5 MB) and the message resource struts.messages.error.file.too.large (the app locale is pt_BR, so the message is in portuguese, not english).
The app current configuration follows:
struts.properties
struts.locale=pt_BR
struts.custom.i18n.resources=MessageResources
struts.xml
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="login" class="br.com.probank.interceptor.LoginInterceptor"/>
<interceptor-stack name="defaultLoginStack">
<interceptor-ref name="login" />
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="defaultLoginStack" />
...
</package>
...
<package name="proposta" namespace="/proposta" extends="default">
<action name="salvarAnexoProposta" method="salvarAnexoProposta" class="br.com.probank.action.AnexoPropostaAction">
<interceptor-ref name="defaultLoginStack">
<param name="fileUpload.maximumSize">5242880</param>
</interceptor-ref>
<result name="success">/jsp/listagemAnexosPropostaForm.jsp</result>
<result name="input">/jsp/crudAnexoPropostaForm.jsp</result>
<result name="error">/jsp/error.jsp</result>
<result name="redirect" type="redirect">${redirectLink}</result>
</action>
</package>
MessageResources.properties
...
struts.messages.error.file.too.large=O tamanho do arquivo...
There is nothing special about my Action implementation and my JSP code. They follow the example found http://struts.apache.org/2.1.6/docs/file-upload-interceptor.html. When I try to upload a file with more than 5 MB the app shows the message "the request was rejected because its size (6229458) exceeds the configured maximum (2097152)" - the default File Upload message with the default maximumSize value.
I try to put the message resource struts.messages.error.file.too.large in a struts-messages.properties but the message didn't change after that. What is the proper way to configure the File Upload Interceptor? I'm using Struts 2 2.1.7. Thanks in advance.
Finally solved the entire puzzle! struts.xml and MessageResource.properties were correctly configured. The problem was struts.multipart.maxSize value. This value have to be bigger than the desired upload limit (5242880 in my app), so I set it as 10000000. If struts.multipart.maxSize value is equal or less then fileUpload.maximumSize the library used by Struts 2 to do the upload stops the upload process (and writes the error message) before the file upload interceptor has a chance to do its job.
The solution provided by you isn't entirely correct in the sense that If I want strict upload limits along with i18n, this won't work. I've also created an issue with strut2 for this. Please look at the following link https://issues.apache.org/jira/browse/WW-3177. It's due to be fixed in struts2.1.9 and is already assigned to a struts team member.
In between, I'm using a hack. I browsed the struts2 source code and found the code for FileUploadInterceptor. Using that code, I created my own. Here's the code below. You can find details of problem at the link above. Hope this helps.
import java.io.File;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
public class CustomFileUploaderInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = -4764627478894962478L;
protected static final Logger LOG = LoggerFactory.getLogger(CustomFileUploaderInterceptor.class);
private static final String DEFAULT_MESSAGE = "no.message.found";
protected boolean useActionMessageBundle;
protected Long maximumSize;
protected Set<String> allowedTypesSet = Collections.emptySet();
protected Set<String> allowedExtensionsSet = Collections.emptySet();
public void setUseActionMessageBundle(String value) {
this.useActionMessageBundle = Boolean.valueOf(value);
}
/**
* Sets the allowed extensions
*
* #param allowedExtensions A comma-delimited list of extensions
*/
public void setAllowedExtensions(String allowedExtensions) {
allowedExtensionsSet = TextParseUtil.commaDelimitedStringToSet(allowedExtensions);
}
/**
* Sets the allowed mimetypes
*
* #param allowedTypes A comma-delimited list of types
*/
public void setAllowedTypes(String allowedTypes) {
allowedTypesSet = TextParseUtil.commaDelimitedStringToSet(allowedTypes);
}
/**
* Sets the maximum size of an uploaded file
*
* #param maximumSize The maximum size in bytes
*/
public void setMaximumSize(Long maximumSize) {
this.maximumSize = maximumSize;
}
/* (non-Javadoc)
* #see com.opensymphony.xwork2.interceptor.Interceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
*/
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
Map<String, Object> params1 = ac.getParameters();
Set<String> keySet = params1.keySet();
for(String s : keySet){
LOG.debug("Key: "+ s +", Value: " + params1.get(s).toString());
}
HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
if (!(request instanceof MultiPartRequestWrapper)) {
if (LOG.isDebugEnabled()) {
ActionProxy proxy = invocation.getProxy();
LOG.debug(getTextMessage("struts.messages.bypass.request", new Object[]{proxy.getNamespace(), proxy.getActionName()}, ac.getLocale()));
}
return invocation.invoke();
}
ValidationAware validation = null;
Object action = invocation.getAction();
if (action instanceof ValidationAware) {
validation = (ValidationAware) action;
}
MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;
if (multiWrapper.hasErrors()) {
String inputName = null;
if(multiWrapper.getFileParameterNames().hasMoreElements()){
inputName = (String)multiWrapper.getFileParameterNames().nextElement();
}
for (String error : multiWrapper.getErrors()) {
if (validation != null) {
Object[] args = new Object[]{inputName};
validation.addActionError(getTextMessage(action, "struts.messages.error.file.too.large", args, ac.getLocale()));
}
LOG.error(error);
}
}
// bind allowed Files
Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
// get the value of this input tag
String inputName = (String) fileParameterNames.nextElement();
// get the content type
String[] contentType = multiWrapper.getContentTypes(inputName);
if (isNonEmpty(contentType)) {
// get the name of the file from the input tag
String[] fileName = multiWrapper.getFileNames(inputName);
if (isNonEmpty(fileName)) {
// get a File object for the uploaded File
File[] files = multiWrapper.getFiles(inputName);
if (files != null && files.length > 0) {
List<File> acceptedFiles = new ArrayList<File>(files.length);
List<String> acceptedContentTypes = new ArrayList<String>(files.length);
List<String> acceptedFileNames = new ArrayList<String>(files.length);
String contentTypeName = inputName + "ContentType";
String fileNameName = inputName + "FileName";
for (int index = 0; index < files.length; index++) {
if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation, ac.getLocale())) {
acceptedFiles.add(files[index]);
acceptedContentTypes.add(contentType[index]);
acceptedFileNames.add(fileName[index]);
}
}
if (!acceptedFiles.isEmpty()) {
Map<String, Object> params = ac.getParameters();
params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
}
}
} else {
LOG.error(getTextMessage(action, "struts.messages.invalid.file", new Object[]{inputName}, ac.getLocale()));
}
} else {
LOG.error(getTextMessage(action, "struts.messages.invalid.content.type", new Object[]{inputName}, ac.getLocale()));
}
}
// invoke action
String result = invocation.invoke();
// cleanup
fileParameterNames = multiWrapper.getFileParameterNames();
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
String inputValue = (String) fileParameterNames.nextElement();
File[] files = multiWrapper.getFiles(inputValue);
for (File currentFile : files) {
if (LOG.isInfoEnabled()) {
LOG.info(getTextMessage(action, "struts.messages.removing.file", new Object[]{inputValue, currentFile}, ac.getLocale()));
}
if ((currentFile != null) && currentFile.isFile()) {
currentFile.delete();
}
}
}
return result;
}
/**
* Override for added functionality. Checks if the proposed file is acceptable based on contentType and size.
*
* #param action - uploading action for message retrieval.
* #param file - proposed upload file.
* #param contentType - contentType of the file.
* #param inputName - inputName of the file.
* #param validation - Non-null ValidationAware if the action implements ValidationAware, allowing for better
* logging.
* #param locale
* #return true if the proposed file is acceptable by contentType and size.
*/
protected boolean acceptFile(Object action, File file, String filename, String contentType, String inputName, ValidationAware validation, Locale locale) {
boolean fileIsAcceptable = false;
// If it's null the upload failed
if (file == null) {
String errMsg = getTextMessage(action, "struts.messages.error.uploading", new Object[]{inputName}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
LOG.error(errMsg);
} else if (maximumSize != null && maximumSize < file.length()) {
String errMsg = getTextMessage(action, "struts.messages.error.file.too.large", new Object[]{inputName, filename, file.getName(), "" + file.length()}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
LOG.error(errMsg);
} else if ((!allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) {
String errMsg = getTextMessage(action, "struts.messages.error.content.type.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
LOG.error(errMsg);
} else if ((! allowedExtensionsSet.isEmpty()) && (!hasAllowedExtension(allowedExtensionsSet, filename))) {
String errMsg = getTextMessage(action, "struts.messages.error.file.extension.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
LOG.error(errMsg);
} else {
fileIsAcceptable = true;
}
return fileIsAcceptable;
}
/**
* #param extensionCollection - Collection of extensions (all lowercase).
* #param filename - filename to check.
* #return true if the filename has an allowed extension, false otherwise.
*/
private static boolean hasAllowedExtension(Collection<String> extensionCollection, String filename) {
if (filename == null) {
return false;
}
String lowercaseFilename = filename.toLowerCase();
for (String extension : extensionCollection) {
if (lowercaseFilename.endsWith(extension)) {
return true;
}
}
return false;
}
/**
* #param itemCollection - Collection of string items (all lowercase).
* #param item - Item to search for.
* #return true if itemCollection contains the item, false otherwise.
*/
private static boolean containsItem(Collection<String> itemCollection, String item) {
return itemCollection.contains(item.toLowerCase());
}
private static boolean isNonEmpty(Object[] objArray) {
boolean result = false;
for (int index = 0; index < objArray.length && !result; index++) {
if (objArray[index] != null) {
result = true;
}
}
return result;
}
private String getTextMessage(String messageKey, Object[] args, Locale locale) {
return getTextMessage(null, messageKey, args, locale);
}
private String getTextMessage(Object action, String messageKey, Object[] args, Locale locale) {
if (args == null || args.length == 0) {
if ( action != null && useActionMessageBundle) {
return LocalizedTextUtil.findText(action.getClass(), messageKey, locale);
}
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale);
} else {
if ( action != null && useActionMessageBundle) {
return LocalizedTextUtil.findText(action.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
}
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
}
}
}
Try this in your struts.xml, where xxxxxxxx is the limit:
<constant name="struts.multipart.maxSize" value="xxxxxxxxx" />
First use validate method in your action file........
public void validate(){
if(getFileUpload() !=null){
System.out.println("======File size validation before upload: size in bytes: "+getFileUpload().length());
if(getFileUpload().length()>202400){
//Give the size in bytes whatever you want to take
addActionError("File is too large ! Select less than 200Kb file");
}else{
addActionMessage("File Uploaded successfully!");
}
}
}
For complete code,please visit http://knowledge-serve.blogspot.com/2011/10/upload-file-using-in-struts-2.html