upload file

This commit is contained in:
Shaun Chyxion 2018-03-15 22:43:02 +08:00
parent a27752c0b3
commit 267fb19f2e
15 changed files with 97 additions and 70 deletions

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
# See http://help.github.com/ignore-files/ for more about ignoring files. # See http://help.github.com/ignore-files/ for more about ignoring files.
/files
# compiled output # compiled output
/web/dist /web/dist
/web/tmp /web/tmp

View File

@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils;
import com.pudonghot.ambition.crm.model.User; import com.pudonghot.ambition.crm.model.User;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import com.pudonghot.ambition.crm.model.Application; import com.pudonghot.ambition.crm.model.Application;
import org.springframework.web.multipart.MultipartFile;
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles;
import com.pudonghot.ambition.crm.model.CustomerProperty; import com.pudonghot.ambition.crm.model.CustomerProperty;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@ -71,34 +70,14 @@ public class ApplicationController
@RequestMapping(value = "/create", method = RequestMethod.POST) @RequestMapping(value = "/create", method = RequestMethod.POST)
public void create( public void create(
@Valid ApplicationFormForCreate form) { @Valid ApplicationFormForCreate form) {
((ApplicationService) queryService).create(form, null); ((ApplicationService) queryService).create(form);
}
@RequiresRoles(User.ROLE_ADMIN)
@RequestMapping(value = "/create-with-images", method = RequestMethod.POST)
public void create(
@Valid
ApplicationFormForCreate form,
@RequestParam("images")
MultipartFile[] images) {
((ApplicationService) queryService).create(form, images);
} }
@RequiresRoles(User.ROLE_ADMIN) @RequiresRoles(User.ROLE_ADMIN)
@RequestMapping(value = "/update", method = RequestMethod.POST) @RequestMapping(value = "/update", method = RequestMethod.POST)
public void update( public void update(
@Valid ApplicationFormForUpdate form) { @Valid ApplicationFormForUpdate form) {
((ApplicationService) queryService).update(form, null); ((ApplicationService) queryService).update(form);
}
@RequiresRoles(User.ROLE_ADMIN)
@RequestMapping(value = "/update-with-images", method = RequestMethod.POST)
public void update(
@Valid ApplicationFormForUpdate form,
@RequestParam("images")
MultipartFile[] images) {
((ApplicationService) queryService).update(form, images);
} }
/** /**

View File

@ -33,11 +33,11 @@ public class FileController {
public Object file(HttpServletRequest request) { public Object file(HttpServletRequest request) {
String reqUri = request.getRequestURI(); String reqUri = request.getRequestURI();
Assert.state(reqUri.length() > 3, "File name could not be blank"); Assert.state(reqUri.length() > 3, "File name could not be blank");
String fileName = reqUri.substring((request.getContextPath() + "/f/").length()); final String fileName = reqUri.substring(
(request.getContextPath() + "/f/").length()).replaceAll("\\.\\w+$", "");
log.info("Get file [{}].", fileName); log.info("Get file [{}].", fileName);
final FileInfo fileInfo = fileInfoMapper.find(new Search(FileInfo.NAME, final FileInfo fileInfo = fileInfoMapper.find(new Search(FileInfo.NAME, fileName));
fileName.replaceAll("\\.\\w+$", "")));
ResourceModel rm = null; ResourceModel rm = null;
if (fileInfo != null) { if (fileInfo != null) {
File file = fileApi.getFile(fileName); File file = fileApi.getFile(fileName);
@ -47,7 +47,7 @@ public class FileController {
rm.setName(fileInfo.getDownloadName()); rm.setName(fileInfo.getDownloadName());
} }
} }
return rm != null ? return rm != null ?
rm : ResponseEntity.notFound().build(); rm : ResponseEntity.notFound().build();
} }
} }

View File

@ -1,12 +1,8 @@
package com.pudonghot.ambition.crm.service; package com.pudonghot.ambition.crm.service;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import com.pudonghot.ambition.crm.form.update.ApplicationFormForUpdate;
import me.chyxion.tigon.service.BaseCrudService;
import com.pudonghot.ambition.crm.model.Application; import com.pudonghot.ambition.crm.model.Application;
import org.springframework.web.multipart.MultipartFile; import me.chyxion.tigon.service.BaseCrudByFormService;
import com.pudonghot.ambition.crm.form.update.ApplicationFormForUpdate;
import com.pudonghot.ambition.crm.form.create.ApplicationFormForCreate; import com.pudonghot.ambition.crm.form.create.ApplicationFormForCreate;
/** /**
@ -15,10 +11,6 @@ import com.pudonghot.ambition.crm.form.create.ApplicationFormForCreate;
* Jun 23, 2017 21:35:24 * Jun 23, 2017 21:35:24
*/ */
public interface ApplicationService public interface ApplicationService
extends BaseCrudService<String, Application> { extends BaseCrudByFormService<String, Application, ApplicationFormForCreate, ApplicationFormForUpdate> {
void create(@NotNull @Valid ApplicationFormForCreate form, MultipartFile[] images);
void update(@NotNull @Valid ApplicationFormForUpdate form, MultipartFile[] images);
} }

View File

@ -4,6 +4,7 @@ import java.util.Date;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.chyxion.tigon.model.ViewModel;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.pudonghot.ambition.file.AmbitionFileApi; import com.pudonghot.ambition.file.AmbitionFileApi;
import com.pudonghot.ambition.crm.model.Application; import com.pudonghot.ambition.crm.model.Application;
@ -37,17 +38,20 @@ public class ApplicationServiceSupport
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void create(final ApplicationFormForCreate form, final MultipartFile[] images) { public ViewModel<Application> create(final ApplicationFormForCreate form) {
final String id = idSeq.get(); final String id = idSeq.get();
final Application application = form.copy(new Application()); final Application application = form.copy(new Application());
application.setId(id); application.setId(id);
final Date now = new Date(); final Date now = new Date();
application.setDateUpdated(now); application.setDateUpdated(now);
final MultipartFile[] images = form.getImages();
if (images != null) { if (images != null) {
final String createdBy = form.getCreatedBy(); final String createdBy = form.getCreatedBy();
int sort = 0; int sort = 0;
final String imageFolder = imageFolder(id); final String imageFolder = imageFolder(id);
final String[] imageTitles = form.getImageTitles();
int i = 0;
for (final MultipartFile image : images) { for (final MultipartFile image : images) {
if (!image.isEmpty()) { if (!image.isEmpty()) {
try (final InputStream ins = image.getInputStream()) { try (final InputStream ins = image.getInputStream()) {
@ -57,26 +61,29 @@ public class ApplicationServiceSupport
appImage.setId(imageId); appImage.setId(imageId);
appImage.setApplicationId(id); appImage.setApplicationId(id);
appImage.setSort(sort++); appImage.setSort(sort++);
appImage.setNote(imageTitles[i]);
appImage.setCreatedBy(createdBy); appImage.setCreatedBy(createdBy);
appImage.setDateCreated(now); appImage.setDateCreated(now);
imageMapper.insert(appImage); imageMapper.insert(appImage);
} }
catch (IOException e) { catch (final IOException e) {
throw new IllegalStateException( throw new IllegalStateException(
"Read upload image [" + image.getOriginalFilename() + "] error cased", e); "Read upload image [" + image.getOriginalFilename() + "] error cased", e);
} }
} }
++i;
} }
} }
mapper.insert(application); mapper.insert(application);
return toViewModel(application);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void update(final ApplicationFormForUpdate form, final MultipartFile[] images) { public ViewModel<Application> update(final ApplicationFormForUpdate form) {
return null;
} }
private String imageFolder(final String appId) { private String imageFolder(final String appId) {

View File

@ -172,7 +172,7 @@ public class DiskFileSupport
final FileInfo fileInfo = fileInfoMapper.find(nameSearch(name)); final FileInfo fileInfo = fileInfoMapper.find(nameSearch(name));
Assert.state(fileInfo != null, Assert.state(fileInfo != null,
"No File [" + name + "] Found"); "No File [" + name + "] Found");
return getFile(fileInfo.getFilePath(), fileInfo.getFormat()); return new File(getFileDir(), fileInfo.getFilePath());
} }
/** /**
@ -221,12 +221,6 @@ public class DiskFileSupport
return new Search(FileInfo.NAME, name); return new Search(FileInfo.NAME, name);
} }
private File getFile(final String name, String format) {
return new File(getFileDir(),
StringUtils.isNotBlank(format) ?
name + "." + format : name);
}
File getFileDir() { File getFileDir() {
File baseFileDir = new File(baseDir); File baseFileDir = new File(baseDir);
if (!baseFileDir.exists()) { if (!baseFileDir.exists()) {
@ -279,9 +273,9 @@ public class DiskFileSupport
String filePath = null; String filePath = null;
if (StringUtils.isNotBlank(name)) { if (StringUtils.isNotBlank(name)) {
log.debug("Name [{}] Is Not Blank.", name); log.debug("Name [{}] is not blank.", name);
if (name.startsWith(basePath)) { if (name.startsWith(basePath)) {
log.debug("Name Starts With Base Path [{}], Trim.", basePath); log.debug("Name starts with base path [{}], trim.", basePath);
filePath = name.replaceFirst(basePath, ""); filePath = name.replaceFirst(basePath, "");
} }
else { else {

View File

@ -3,7 +3,10 @@ package com.pudonghot.ambition.crm.form.create;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import me.chyxion.tigon.form.FC2; import me.chyxion.tigon.form.FC2;
import me.chyxion.tigon.format.annotation.Trim;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import me.chyxion.tigon.format.annotation.EmptyToNull;
import org.springframework.web.multipart.MultipartFile;
/** /**
* @author Shaun Chyxion <br> * @author Shaun Chyxion <br>
@ -16,8 +19,15 @@ public class ApplicationFormForCreate extends FC2<String> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
// Properties // Properties
@Trim
@NotBlank @NotBlank
private String name; private String name;
@Trim
@EmptyToNull
private String content; private String content;
@Trim
@EmptyToNull
private String owner; private String owner;
private String[] imageTitles;
private MultipartFile[] images;
} }

View File

@ -3,8 +3,11 @@ package com.pudonghot.ambition.crm.form.update;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import me.chyxion.tigon.form.FU2; import me.chyxion.tigon.form.FU2;
import me.chyxion.tigon.format.annotation.Trim;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import me.chyxion.tigon.format.annotation.EmptyToNull;
import org.springframework.web.multipart.MultipartFile;
/** /**
* @version 0.0.1 * @version 0.0.1
@ -21,4 +24,12 @@ public class ApplicationFormForUpdate extends FU2<String, String> {
@NotBlank @NotBlank
@Length(max = 64) @Length(max = 64)
private String name; private String name;
@Trim
@EmptyToNull
private String content;
@Trim
@EmptyToNull
private String owner;
private String[] imageTitles;
private MultipartFile[] images;
} }

View File

@ -1,7 +1,10 @@
import Ember from 'ember'; import Ember from 'ember';
import Component from '@ember/component'; import Component from '@ember/component';
import { computed } from '@ember/object';
export default Component.extend({ export default Component.extend({
image: {},
value: computed.alias('image.file'),
didReceiveAttrs() { didReceiveAttrs() {
const me = this; const me = this;
me._super(...arguments); me._super(...arguments);

View File

@ -1,25 +1,29 @@
import Ember from 'ember'; import Ember from 'ember';
import BaseRoute from '../base'; import BaseRoute from '../base';
import EmberObject, { computed } from '@ember/object';
export default BaseRoute.extend({ export default BaseRoute.extend({
service: Ember.inject.service('customer-property.service'),
breadcrumbs: [{route: 'customer-application.list', params: 1, text: 'Customer Application'}, breadcrumbs: [{route: 'customer-application.list', params: 1, text: 'Customer Application'},
{text: 'Create Customer Application'}], {text: 'Create Customer Application'}],
modelClass: EmberObject.extend({
hasImage: computed('images.@each.file', function() {
return this.get('images').filter(image => image.file).length > 0;
})
}),
model() { model() {
return { return this.get('modelClass').create({
type: 'APPLICATION',
enabled: true, enabled: true,
images: [{}] images: [{}]
}; });
}, },
actions: { actions: {
addImage() { addImage() {
const me = this; const me = this;
me.get('controller.model.images').pushObject({}); me.get('controller.model.images').pushObject({});
}, },
removeImage(img) { removeImage(image) {
const me = this; const me = this;
me.get('controller.model.images').removeObject(img); me.get('controller.model.images').removeObject(image);
}, },
} }
}); });

View File

@ -1,9 +1,9 @@
import Ember from 'ember'; import Ember from 'ember';
import CustomerPropertyListRoute from './../customer-property/list'; import BaseListRoute from './../base-list';
export default CustomerPropertyListRoute.extend({ export default BaseListRoute.extend({
breadcrumbs: [{text: 'Customer Application'}], breadcrumbs: [{text: 'Customer Application'}],
model(params) { // model(params) {
return this.get('store').ajaxGet('customer-property/app-list', params); // return this.get('store').ajaxGet('customer-property/app-list', params);
} // }
}); });

View File

@ -0,0 +1,15 @@
import Ember from 'ember';
import BaseService from '../service';
export default BaseService.extend({
modelName: 'Application',
constraints: {
name: {
presence: true,
length: {
minimum: 1,
maximum: 36
}
}
}
});

View File

@ -17,16 +17,16 @@
<div class="widget-body"> <div class="widget-body">
<div class="widget-main padding-4"> <div class="widget-main padding-4">
<!-- #section:pages/profile.feed --> <!-- #section:pages/profile.feed -->
{{#each model.images as |img|}} {{#each model.images as |image i|}}
<div class="col-xs-6 no-padding-left"> <div class="col-xs-6 no-padding-left">
<div class="space-4"></div> <div class="space-4"></div>
{{input name='imageTitle' class='width-80' placeholder='Image title'}} {{input name=(concat 'imageTitles[' i ']') class='width-80' placeholder='Image title' value=image.title}}
&nbsp; &nbsp;
<a href="#" class="red" data-rel="tooltip" title="Remove Image" {{action (route-action 'removeImage' img)}}> <a href="#" class="red" data-rel="tooltip" title="Remove Image" {{action (route-action 'removeImage' image)}}>
<i class="ace-icon fa fa-times bigger-125"></i> <i class="ace-icon fa fa-times bigger-125"></i>
</a> </a>
<div class="space-2"></div> <div class="space-2"></div>
{{image-input name='image'}} {{image-input name=(concat 'images[' i ']') image=image}}
</div> </div>
{{/each}} {{/each}}
<!-- /section:pages/profile.feed --> <!-- /section:pages/profile.feed -->
@ -34,8 +34,6 @@
</div> </div>
</div> </div>
{{/form-input}} {{/form-input}}
{{!form-input type='image' name='images' label='Image' input-class='col-xs-2'}}
{{!form-input-enabled label='Enabled' enabledText='TRUE' disabledText='FALSE'}}
{{form-input name='note' label='Remark'}} {{form-input name='note' label='Remark'}}
<hr /> <hr />
{{form-footer-buttons}} {{form-footer-buttons}}

View File

@ -117,7 +117,7 @@
</tbody> </tbody>
</table> </table>
</div> </div>
{{!pagination-bar}} {{pagination-bar}}
</div> </div>
</div> </div>
{{/main-content}} {{/main-content}}

View File

@ -0,0 +1,12 @@
import { moduleFor, test } from 'ember-qunit';
moduleFor('service:customer-application/service', 'Unit | Service | customer application/service', {
// Specify the other units that are required for this test.
// needs: ['service:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let service = this.subject();
assert.ok(service);
});