tomdesair / tus-java-server

Library to receive tus v1.0.0 file uploads in a Java server environment
MIT License
128 stars 60 forks source link

How to make the uploaded file on the server with corrected file extension? #20

Open softboy99 opened 5 years ago

softboy99 commented 5 years ago

How to make the uploaded file on the server with corrected file extension? Currently, the uploaded file on the server has no file extensions. All of them is named "data".

tomdesair commented 5 years ago

Hi @softboy99,

The tus protocol itself makes abstraction of files: "the specification does not have the principle of a disk-based file, allowing you to upload arbitrary data using tus" (https://tus.io/protocols/resumable-upload.html#how-can-i-get-the-file-name-or-file-type-for-an-upload). This means the tus Java server implementation cannot rely on the fact that an upload is always a "file". It could also be for example a video stream.

In addition, you should always consider the upload directory as a temporary directory. You should not use it as the permanent destination of the uploaded bytes.

However, the Uppy file uploader does provide the filename as metadata. The tus Java server implementation supports this through the getFileName() method. But note that this method only gives a meaningful value if you upload files with Uppy (or any other uploader that passes the filename as metadata). So if you are uploading files with Uppy, you could copy the uploaded bytes to their final destination in a new file with the correct name.

For example we could extend the Dropwizard example to

if(!uploadInfo.isUploadInProgress()) {
    InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(url, ownerKey);

    Path newFile = Paths.get("my/target/directory", uploadInfo.getFileName());

    java.nio.file.Files.copy(
        uploadedBytes, 
        newFile, 
        StandardCopyOption.REPLACE_EXISTING);

    //Since we're done with processing the upload, we can safely remove it now
    tusFileUploadService.deleteUpload(url, ownerKey);
}

Does this answer your questions?

softboy99 commented 5 years ago

Hi do you mean the meta data be request header or body set by the client?

softboy99 commented 5 years ago

Hi, My uploadInfo alwasy be null. I'm using it in spring boot rest controller. after tusFileUploadService.process call. Can you help me? Thanks a lot

softboy99 commented 5 years ago

Hi, The following is my code: `try { tusFileUploadService.process(servletRequest, servletResponse); String hLocation = servletResponse.getHeader(HttpHeader.LOCATION); if(hLocation!=null){ UploadInfo ui = tusFileUploadService.getUploadInfo(hLocation); if(ui!=null && !ui.isUploadInProgress()) { InputStream uploadedBytes = tusFileUploadService.getUploadedBytes(hLocation); Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String[] sDateArr = sdf.format(d).split("-"); String fileName = servletRequest.getHeader("fileName"); Path newFile = Paths.get(tusDataPath,sDateArr[0],sDateArr[1],sDateArr[2], fileName); java.nio.file.Files.copy(uploadedBytes, newFile, StandardCopyOption.REPLACE_EXISTING); //Since we're done with processing the upload, we can safely remove it now tusFileUploadService.deleteUpload(hLocation); String entityName = servletRequest.getHeader("entityName"); String fieldName = servletRequest.getHeader("fieldName"); String keyName = servletRequest.getHeader("keyName"); String keyValue = servletRequest.getHeader("keyValue"); String uploadType = servletRequest.getHeader("uploadType"); String deviceNo = servletRequest.getHeader("deviceNo"); long operId = Long.parseLong(servletRequest.getHeader("operId")); servletResponse.setHeader("Location",newFile.toString()); //fileUploadService.updateFileLocation(uploadType,entityName,fieldName,newFile.toString(),keyName,keyValue,deviceNo,operId); } }

    } catch (IOException | TusException e) {
        e.printStackTrace();
    }`

if(ui!=null && !ui.isUploadInProgress()) never be executed

softboy99 commented 5 years ago

Hi, @tomdesair , could you please help me? Thanks a lot!

tomdesair commented 5 years ago

Hi @softboy99,

You need to provide any metadata about the upload (like mime-type, filename, ...) in the Upload-Metadata HTTP header. Make sure to read this: https://tus.io/protocols/resumable-upload.html#upload-metadata

For example if you provide the header Upload-Metadata: filename d29ybGRfZG9taW5hdGlvbiBwbGFuLnBkZg==,mimetype YXBwbGljYXRpb24vcGRm when creating the upload, the library will parse the metadata in that header. The UploadInfo.getMetadata() method will then return a Map containing entries ("filename", "world_domination plan.pdf") and ("mimetype", "application/pdf"). Method UploadInfo.getFileName() will look for the filename entry and will thus return world_domination plan.pdf in this example.

Also see this unit test.

Does this help?

tomdesair commented 5 years ago

You can also take a look at this example from another developer: