Merge branch 'DS-3580_workspaceitem' of https://github.com/4Science/DSpace into inputform-rows

This commit is contained in:
Andrea Bollini
2018-10-10 11:45:02 +02:00
8 changed files with 89 additions and 46 deletions

View File

@@ -444,8 +444,6 @@ public class RestResourceController implements InitializingBean {
* the rest model that identify the REST resource collection
* @param id
* the id of the specific rest resource
* @param extraField
* the original name of the uploaded file
* @param uploadfile
* the file to upload
* @return the created resource
@@ -457,12 +455,10 @@ public class RestResourceController implements InitializingBean {
@PathVariable String apiCategory,
@PathVariable String model,
@PathVariable Integer id,
@RequestParam(required = false, value =
"extraField") String extraField,
@RequestParam("file") MultipartFile
uploadfile)
throws HttpRequestMethodNotSupportedException {
return uploadInternal(request, apiCategory, model, id, extraField, uploadfile);
return uploadInternal(request, apiCategory, model, id, uploadfile);
}
/**
@@ -478,8 +474,6 @@ public class RestResourceController implements InitializingBean {
* the rest model that identify the REST resource collection
* @param id
* the id of the specific rest resource
* @param extraField
* the original name of the uploaded file
* @param uploadfile
* the file to upload
* @return the created resource
@@ -491,12 +485,10 @@ public class RestResourceController implements InitializingBean {
@PathVariable String apiCategory,
@PathVariable String model,
@PathVariable UUID id,
@RequestParam(required = false, value =
"extraField") String extraField,
@RequestParam("file") MultipartFile
uploadfile)
throws HttpRequestMethodNotSupportedException {
return uploadInternal(request, apiCategory, model, id, extraField, uploadfile);
return uploadInternal(request, apiCategory, model, id, uploadfile);
}
/**
@@ -506,21 +498,19 @@ public class RestResourceController implements InitializingBean {
* @param apiCategory
* @param model
* @param id
* @param extraField
* @param uploadfile
* @return
*/
private <ID extends Serializable> ResponseEntity<ResourceSupport> uploadInternal(HttpServletRequest request,
String apiCategory, String model,
ID id,
String extraField,
MultipartFile uploadfile) {
checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model);
RestAddressableModel modelObject = null;
try {
modelObject = repository.upload(request, apiCategory, model, id, extraField, uploadfile);
modelObject = repository.upload(request, apiCategory, model, id, uploadfile);
} catch (Exception e) {
log.error(e.getMessage(), e);
return ControllerUtils.toEmptyResponse(HttpStatus.INTERNAL_SERVER_ERROR);
@@ -552,8 +542,6 @@ public class RestResourceController implements InitializingBean {
public <T extends RestAddressableModel> ResponseEntity<ResourceSupport> upload(HttpServletRequest request,
@PathVariable String apiCategory,
@PathVariable String model,
@RequestParam(required = false)
String extraField,
@RequestParam("file") MultipartFile
uploadfile)
throws SQLException, FileNotFoundException, IOException, AuthorizeException {
@@ -561,7 +549,7 @@ public class RestResourceController implements InitializingBean {
checkModelPluralForm(apiCategory, model);
DSpaceRestRepository repository = utils.getResourceRepository(apiCategory, model);
Iterable<T> content = repository.upload(request, extraField, uploadfile);
Iterable<T> content = repository.upload(request, uploadfile);
List<DSpaceResource> resources = new ArrayList<>();
for (T modelObject : content) {

View File

@@ -298,15 +298,13 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
* @param model
* @param id
* the ID of the target REST object
* @param extraField
* the original name of the uploaded file
* @param file
* the uploaded file
* @return the new state of the REST object
* @throws Exception
*/
public T upload(HttpServletRequest request, String apiCategory, String model,
ID id, String extraField, MultipartFile file) throws Exception {
ID id, MultipartFile file) throws Exception {
throw new RuntimeException("No implementation found; Method not allowed!");
}
@@ -373,8 +371,6 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
*
* @param request
* the http request
* @param extraField
* the original name of the uploaded file
* @param uploadfile
* the file to process
* @return the created objects
@@ -383,10 +379,10 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
* @throws IOException
* @throws AuthorizeException
*/
public Iterable<T> upload(HttpServletRequest request, String extraField, MultipartFile uploadfile)
public Iterable<T> upload(HttpServletRequest request, MultipartFile uploadfile)
throws SQLException, FileNotFoundException, IOException, AuthorizeException {
Context context = obtainContext();
Iterable<T> entity = upload(context, request, extraField, uploadfile);
Iterable<T> entity = upload(context, request, uploadfile);
context.commit();
return entity;
}
@@ -396,8 +392,6 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
*
* @param request
* the http request
* @param extraField
* the original name of the uploaded file
* @param uploadfile
* the file to process
* @return the created objects
@@ -407,7 +401,7 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
* @throws AuthorizeException
* @throws RepositoryMethodNotImplementedException
*/
protected Iterable<T> upload(Context context, HttpServletRequest request, String extraField,
protected Iterable<T> upload(Context context, HttpServletRequest request,
MultipartFile uploadfile)
throws SQLException, FileNotFoundException, IOException, AuthorizeException {
throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", "");

View File

@@ -219,7 +219,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
//TODO @PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'WRITE')")
@Override
public WorkspaceItemRest upload(HttpServletRequest request, String apiCategory, String model, Integer id,
String extraField, MultipartFile file) throws Exception {
MultipartFile file) throws Exception {
Context context = obtainContext();
WorkspaceItemRest wsi = findOne(id);
@@ -244,7 +244,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
UploadableStep uploadableStep = (UploadableStep) stepInstance;
uploadableStep.doPreProcessing(context, source);
ErrorRest err =
uploadableStep.upload(context, submissionService, stepConfig, source, file, extraField);
uploadableStep.upload(context, submissionService, stepConfig, source, file);
uploadableStep.doPostProcessing(context, source);
if (err != null) {
errors.add(err);
@@ -347,7 +347,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
}
@Override
public Iterable<WorkspaceItemRest> upload(Context context, HttpServletRequest request, String extraField,
public Iterable<WorkspaceItemRest> upload(Context context, HttpServletRequest request,
MultipartFile uploadfile)
throws SQLException, FileNotFoundException, IOException, AuthorizeException {
File file = Utils.getFile(uploadfile, "upload-loader", "filedataloader");
@@ -467,7 +467,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
if (UploadableStep.class.isAssignableFrom(stepClass)) {
UploadableStep uploadableStep = (UploadableStep) stepInstance;
ErrorRest err = uploadableStep.upload(context, submissionService, stepConfig, wi,
uploadfile, extraField);
uploadfile);
if (err != null) {
errors.add(err);
}

View File

@@ -23,7 +23,24 @@ import org.springframework.web.multipart.MultipartFile;
*/
public interface UploadableStep extends ListenerProcessingStep {
/**
* The method to implement to support upload of a file in the submission section (aka panel / step)
*
* @param context
* the dspace context
* @param submissionService
* the submission service
* @param stepConfig
* the configuration of the submission section
* @param wsi
* the inprogress submission
* @param file
* the multipart file, please note that it is a complex object containing additional information other
* than just the binary such as the filename and the mimetype
* @return the encountered error if any
* @throws IOException
*/
public ErrorRest upload(Context context, SubmissionService submissionService, SubmissionStepConfig stepConfig,
InProgressSubmission wsi, MultipartFile file, String extraField) throws IOException;
InProgressSubmission wsi, MultipartFile file) throws IOException;
}

View File

@@ -47,7 +47,7 @@ public class ExtractMetadataStep extends ExtractionStep implements UploadableSte
@Override
public ErrorRest upload(Context context, SubmissionService submissionService, SubmissionStepConfig stepConfig,
InProgressSubmission wsi, MultipartFile multipartFile, String extraField)
InProgressSubmission wsi, MultipartFile multipartFile)
throws IOException {
Item item = wsi.getItem();
@@ -66,7 +66,7 @@ public class ExtractMetadataStep extends ExtractionStep implements UploadableSte
}
FileDataLoader fdl = (FileDataLoader) dataLoader;
fdl.setFilename(file.getAbsolutePath());
fdl.setFilename(Utils.getFileName(multipartFile));
recordSet = convertFields(dataLoader.getRecords(), bteBatchImportService.getOutputMap());

View File

@@ -22,6 +22,7 @@ import org.dspace.app.rest.submit.SubmissionService;
import org.dspace.app.rest.submit.UploadableStep;
import org.dspace.app.rest.submit.factory.PatchOperationFactory;
import org.dspace.app.rest.submit.factory.impl.PatchOperation;
import org.dspace.app.rest.utils.Utils;
import org.dspace.app.util.SubmissionStepConfig;
import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat;
@@ -93,7 +94,7 @@ public class UploadStep extends org.dspace.submit.step.UploadStep
@Override
public ErrorRest upload(Context context, SubmissionService submissionService, SubmissionStepConfig stepConfig,
InProgressSubmission wsi, MultipartFile file, String extraField) {
InProgressSubmission wsi, MultipartFile file) {
Bitstream source = null;
BitstreamFormat bf = null;
@@ -113,7 +114,7 @@ public class UploadStep extends org.dspace.submit.step.UploadStep
source = bitstreamService.create(context, bundles.get(0), inputStream);
}
source.setName(context, extraField);
source.setName(context, Utils.getFileName(file));
source.setSource(context, file.getOriginalFilename());
// Identify the format

View File

@@ -165,6 +165,20 @@ public class Utils {
return org.dspace.core.Utils.standardize(schema, element, qualifier, ".");
}
/**
* Create a temporary file from a multipart file upload
*
* @param multipartFile
* the multipartFile representing the uploaded file. Please note that it is a complex object including
* additional information other than the binary like the orginal file name and the mimetype
* @param prefixTempName
* the prefix to use to generate the filename of the temporary file
* @param suffixTempName
* the suffic to use to generate the filename of the temporary file
* @return the temporary file on the server
* @throws IOException
* @throws FileNotFoundException
*/
public static File getFile(MultipartFile multipartFile, String prefixTempName, String suffixTempName)
throws IOException, FileNotFoundException {
// TODO after change item-submission into
@@ -183,4 +197,26 @@ public class Utils {
org.dspace.core.Utils.bufferedCopy(io, out);
return file;
}
/**
* Return the filename part from a multipartFile upload that could eventually contains the fullpath on the client
* filesystem
*
* @param multipartFile
* the file uploaded
* @return the filename part of the file on the client filesystem
* @throws IOException
* @throws FileNotFoundException
*/
public static String getFileName(MultipartFile multipartFile)
throws IOException, FileNotFoundException {
String originalFilename = multipartFile.getOriginalFilename();
if (originalFilename != null) {
// split by \ or / as we don't know the client OS (Win, Linux)
String[] parts = originalFilename.split("[\\/]");
return parts[parts.length - 1];
} else {
return multipartFile.getName();
}
}
}

View File

@@ -486,12 +486,12 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
String authToken = getAuthToken(admin.getEmail(), password);
InputStream bibtex = getClass().getResourceAsStream("bibtex-test.bib");
final MockMultipartFile bibtexFile = new MockMultipartFile("file", bibtex);
final MockMultipartFile bibtexFile = new MockMultipartFile("file", "bibtex-test.bib", "application/x-bibtex",
bibtex);
// bulk create workspaceitems in the default collection (col1)
getClient(authToken).perform(fileUpload("/api/submission/workspaceitems")
.file(bibtexFile)
.param("extraField", "bibtex-test.bib"))
.file(bibtexFile))
// bulk create should return 200, 201 (created) is better for single resource
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.workspaceitems[0].sections.traditionalpageone['dc.title'][0].value",
@@ -506,6 +506,8 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
is("My Article 3")))
.andExpect(
jsonPath("$._embedded.workspaceitems[2]._embedded.collection.id", is(col1.getID().toString())))
.andExpect(
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
;
// bulk create workspaceitems explicitly in the col2
@@ -525,6 +527,8 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
is("My Article 3")))
.andExpect(
jsonPath("$._embedded.workspaceitems[2]._embedded.collection.id", is(col2.getID().toString())))
.andExpect(
jsonPath("$._embedded.workspaceitems[*]._embedded.upload").doesNotExist())
;
bibtex.close();
@@ -558,8 +562,7 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
// bulk create a workspaceitem
getClient(authToken).perform(fileUpload("/api/submission/workspaceitems")
.file(pdfFile)
.param("extraField", "sample-article.pdf"))
.file(pdfFile))
// bulk create should return 200, 201 (created) is better for single resource
.andExpect(status().isOk())
//FIXME it will be nice to setup a mock grobid server for end to end testing
@@ -569,7 +572,7 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
// we can just check that the pdf is stored in the item
.andExpect(
jsonPath("$._embedded.workspaceitems[0].sections.upload.files[0].metadata['dc.title'][0].value",
is("sample-article.pdf")))
is("myfile.pdf")))
.andExpect(jsonPath(
"$._embedded.workspaceitems[0].sections.upload.files[0].metadata['dc.source'][0].value",
is("/local/path/myfile.pdf")))
@@ -1639,22 +1642,26 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
.build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
final MockMultipartFile pdfFile = new MockMultipartFile("file", pdf);
final MockMultipartFile pdfFile = new MockMultipartFile("file", "/local/path/simple-article.pdf",
"application/pdf", pdf);
// upload the file in our workspaceitem
getClient(authToken).perform(fileUpload("/api/submission/workspaceitems/" + witem.getID())
.file(pdfFile)
.param("extraField", "sample-article.pdf"))
.file(pdfFile))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.sections.upload.files[0].metadata['dc.title'][0].value",
is("sample-article.pdf")))
is("simple-article.pdf")))
.andExpect(jsonPath("$.sections.upload.files[0].metadata['dc.source'][0].value",
is("/local/path/simple-article.pdf")))
;
// check the file metadata
getClient().perform(get("/api/submission/workspaceitems/" + witem.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.sections.upload.files[0].metadata['dc.title'][0].value",
is("sample-article.pdf")))
is("simple-article.pdf")))
.andExpect(jsonPath("$.sections.upload.files[0].metadata['dc.source'][0].value",
is("/local/path/simple-article.pdf")))
;
}