Skip to content

Commit

Permalink
Feat: Presigned Url (PanJiaChen#1899)
Browse files Browse the repository at this point in the history
* Feat: Presigned Url

* minimal changes

* remove console

* Minamel Change

* remove console
  • Loading branch information
elsiosanchez authored Feb 9, 2024
1 parent a3f5a66 commit ecba283
Show file tree
Hide file tree
Showing 5 changed files with 368 additions and 143 deletions.
38 changes: 37 additions & 1 deletion src/api/ADempiere/file-management/resource-reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { config } from '@/utils/ADempiere/config'
// Get Instance for connection
import { request } from '@/utils/ADempiere/request'

Expand All @@ -27,6 +27,42 @@ import {
// Utils and Helper Methods
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'

/**
* Presigned Url
* @param {string} file_name
*/
export function requestPresignedUrl({
fileName
}) {
return request({
url: `${config.adempiere.resource.url}/presigned-url/${fileName}`,
method: 'get',
isWithoutAuthorization: true,
params: {
file_name: fileName
}
})
}

/**
* Upload File
* @param {string} url
*/

export function requestUploadFile({
url,
file
}) {
return request({
url: `${url}`,
method: 'put',
isWithoutAuthorization: true,
body: {
file
}
})
}

/**
* Set resource reference
* @param {number} resourceId
Expand Down
79 changes: 50 additions & 29 deletions src/components/ADempiere/FieldDefinition/FieldImage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,12 @@ import { config } from '@/utils/ADempiere/config'
import { BEARER_TYPE } from '@/utils/auth'
import { MIME_TYPE_IMAGE } from '@/utils/ADempiere/resource/image.ts'
import { UUID_PATTERN } from '@/utils/ADempiere/recordUtil'
import { RESOURCE_TYPE_IMAGE } from '@/utils/ADempiere/resource'
// import { RESOURCE_TYPE_IMAGE } from '@/utils/ADempiere/resource'

// API Request Methods
import {
requestSetResourceReference,
requestPresignedUrl,
// requestSetResourceReference,
requestDeleteResourceReference
} from '@/api/ADempiere/file-management/resource-reference.ts'

Expand Down Expand Up @@ -251,7 +252,6 @@ export default {
// // height: 200,
// // operation: 'resize'
// // })
// console.log(blobImage)
// return blobImage.href
// },
endPointUploadResource() {
Expand Down Expand Up @@ -328,34 +328,55 @@ export default {
reject(false)
return
}
requestSetResourceReference({
resourceType: RESOURCE_TYPE_IMAGE,
id: this.value || -1,
fileName: file.name,
fileSize: file.size
}).then(response => {
if (response.code >= 400) {
reject(response)
requestPresignedUrl({
fileName: file.name
})
.then(responseUrl => {
fetch(responseUrl, {
method: 'PUT',
body: file
}).then(() => {
// If multiple files are uploaded, append upload status on the next line.
}).catch((e) => {
console.error(e)
})
})
.catch(error => {
showMessage({
message: error.message || error.result || lang.t('component.attachment.error'),
type: 'error'
})
reject(error)
return
}

this.fileResource = response
this.additionalData = {
id: response.id
// file_name: response.file_name
}

this.value = response.resource_id
this.displayedValue = response.file_name
this.preHandleChange(this.value)
resolve(true)
}).catch(error => {
showMessage({
message: error.message || error.result || lang.t('component.attachment.error'),
type: 'error'
})
reject(error)
})
// requestSetResourceReference({
// resourceType: RESOURCE_TYPE_IMAGE,
// id: this.value || -1,
// fileName: file.name,
// fileSize: file.size
// }).then(response => {
// if (response.code >= 400) {
// reject(response)
// return
// }

// this.fileResource = response
// this.additionalData = {
// id: response.id
// // file_name: response.file_name
// }

// this.value = response.resource_id
// this.displayedValue = response.file_name
// this.preHandleChange(this.value)
// resolve(true)
// }).catch(error => {
// showMessage({
// message: error.message || error.result || lang.t('component.attachment.error'),
// type: 'error'
// })
// reject(error)
// })
})
},
handleChange(file, fileList) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,54 +17,49 @@
-->

<template>
<form
enctype="multipart/form-data"
@submit.prevent="notSubmitForm"
>
<span>
<!-- <input id="selector" type="file" multiple>
<button @click="upload()">Upload</button>
<div id="status">No uploads</div>' -->
<el-upload
ref="uploadComponent"
:action="endPointUploadResource + fileResource.id"
:action="action"
class="upload-demo"
name="file"
:file-list="filesList"
:data="additionalData"
:headers="additionalHeaders"
:multiple="false"
:before-upload="isValidUploadHandler"
:on-success="loadedSucess"
:on-error="handleError"
:multiple="false"
>
<el-button slot="trigger" size="small" type="primary" style="font-size: 13px;">
<i class="el-icon-upload" />
{{ $t('component.attachment.uploadFile') }}
</el-button>
</el-upload>
</form>
</span>
</template>

<script>
import { defineComponent, computed, ref } from '@vue/composition-api'
import { defineComponent, ref } from '@vue/composition-api'

import lang from '@/lang'
import store from '@/store'
// import lang from '@/lang'
// import store from '@/store'

// Constants
import { config } from '@/utils/ADempiere/config'
import { BEARER_TYPE } from '@/utils/auth'
import { RESOURCE_TYPE_ATTACHMENT } from '@/utils/ADempiere/resource'
// import { config } from '@/utils/ADempiere/config'
// import { BEARER_TYPE } from '@/utils/auth'
// import { RESOURCE_TYPE_ATTACHMENT } from '@/utils/ADempiere/resource'

// API Request Methods
// import {
// // requestUploadAttachment
// } from '@/api/ADempiere/user-interface/component/resource'
import {
requestSetResourceReference
requestPresignedUrl
} from '@/api/ADempiere/file-management/resource-reference.ts'

// Utils and Helper Methods
import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
import { showMessage } from '@/utils/ADempiere/notification'
import { getToken } from '@/utils/auth'
// // Utils and Helper Methods
// import { isEmptyValue } from '@/utils/ADempiere/valueUtils'
// import { showMessage } from '@/utils/ADempiere/notification'
// import { getToken } from '@/utils/auth'
// import { convertStringToBoolean } from '@/utils/ADempiere/formatValue/booleanFormat'

export default defineComponent({
name: 'UploadResource',
Expand All @@ -86,106 +81,61 @@ export default defineComponent({
},

setup(props) {
const endPointUploadResource = config.adempiere.api.url + 'file-management/resources/'

const uploadComponent = ref(null)
const filesList = ref([])
const additionalData = ref({})
const fileResource = ref(({}))

const additionalHeaders = computed(() => {
const token = getToken()
let bearerToken = token
// Json Web Token
if (!isEmptyValue(bearerToken) && !bearerToken.startsWith(BEARER_TYPE)) {
bearerToken = `${BEARER_TYPE} ${token}`
}
return {
Authorization: bearerToken
}
})
const action = ref('')
function upload() {
// // Get selected files from the input element.
// var files = document.querySelector('#selector').files
// for (var i = 0; i < files.length; i++) {
// var file = files[i]
// // Retrieve a URL from our server.
// retrieveNewURL(file, (file, url) => {
// // Upload the file to the server.
// uploadFile(file, url)
// })
// }
}

function isValidUploadHandler(file) {
return new Promise((resolve, reject) => {
requestSetResourceReference({
resourceType: RESOURCE_TYPE_ATTACHMENT,
tableName: props.tableName,
recordId: props.recordId,
fileName: file.name,
fileSize: file.size
}).then(response => {
if (response.code >= 400) {
reject(response)
}
// endPointUploadResource += response.id

fileResource.value = response
additionalData.value = {
// resource_uuid: response.uuid,
id: response.id,
file_name: response.file_name
}
resolve(true)
}).catch(error => {
showMessage({
message: error.message || error.result || lang.t('component.attachment.error'),
type: 'error'
})
reject(error)
}).finally(() => {
// uploadComponent.value.uploadFiles = filesList.value
// resolve(true)
})
})
retrieveNewURL(file)
}

function handleError(error, file, fileList) {
return showMessage({
type: 'error',
message: error.message || error.result || lang.t('component.attachment.error')
function retrieveNewURL(file, cb) {
return new Promise(resolve => {
requestPresignedUrl({
fileName: file.name.replaceAll(' ', '_')
})
.then(response => {
action.value = response
uploadFile(file, response)
resolve(file, response)
})
})
// fetch(`/presignedUrl?name=${file.name}`).then((response) => {
// response.text().then((url) => {
// cb(file, url)
// })
// }).catch((e) => {
// console.error(e)
// })
}

function loadedSucess(response, file, fileList) {
if (response.code >= 400) {
setTimeout(() => {
fileList.pop()
}, 500)
return handleError(
new Error(response.result),
file,
fileList
)
}

if (props.loadData) {
props.loadData({
resource: fileResource.value,
file
})
}
additionalData.value = {}

store.dispatch('getAttachmentFromServer', {
tableName: props.tableName,
recordId: props.recordId,
recordUuid: props.recordUuid
// ``uploadFile` accepts the current filename and the pre-signed URL. It then uses `Fetch API`
// to upload this file to S3 at `play.min.io:9000` using the URL:
function uploadFile(file, url) {
fetch(url, {
method: 'PUT',
body: file
}).then(() => {
// If multiple files are uploaded, append upload status on the next line.
}).catch((e) => {
console.error(e)
})
}

return {
endPointUploadResource,
// Refs
uploadComponent,
additionalData,
fileResource,
filesList,
// Computeds
additionalHeaders,
// Methods
upload,
isValidUploadHandler,
loadedSucess,
handleError
action
}
}
})
Expand Down
Loading

0 comments on commit ecba283

Please sign in to comment.